diff --git a/src/WINNT/afsrdr/npdll/AFSRDFSProvder.vcproj b/src/WINNT/afsrdr/npdll/AFSRDFSProvder.vcproj
new file mode 100644
index 0000000000..905c317cb1
--- /dev/null
+++ b/src/WINNT/afsrdr/npdll/AFSRDFSProvder.vcproj
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/WINNT/afsrdr/npdll/AFSRDFSProvder.vcproj.vspscc b/src/WINNT/afsrdr/npdll/AFSRDFSProvder.vcproj.vspscc
new file mode 100644
index 0000000000..f1eb364032
--- /dev/null
+++ b/src/WINNT/afsrdr/npdll/AFSRDFSProvder.vcproj.vspscc
@@ -0,0 +1,10 @@
+""
+{
+"FILE_VERSION" = "9237"
+"ENLISTMENT_CHOICE" = "NEVER"
+"PROJECT_FILE_RELATIVE_PATH" = "relative:AFSRDFSProvider"
+"NUMBER_OF_EXCLUDED_FILES" = "0"
+"ORIGINAL_PROJECT_FILE_PATH" = ""
+"NUMBER_OF_NESTED_PROJECTS" = "0"
+"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
+}
diff --git a/src/WINNT/afsrdr/npdll/AFS_Npdll.DEF b/src/WINNT/afsrdr/npdll/AFS_Npdll.DEF
new file mode 100644
index 0000000000..64cca3bc76
--- /dev/null
+++ b/src/WINNT/afsrdr/npdll/AFS_Npdll.DEF
@@ -0,0 +1,24 @@
+SECTIONS .AFSNP READ WRITE SHARED
+
+EXPORTS
+ DllMain @1
+ NPLogonNotify @7
+ NPPasswordChangeNotify @8
+ NPGetConnection @12
+ NPGetCaps @13
+ NPAddConnection @17
+ NPCancelConnection @18
+ NPOpenEnum @33
+ NPEnumResource @34
+ NPCloseEnum @35
+ NPFormatNetworkName @36
+ NPAddConnection3 @38
+ NPGetUniversalName @40
+ NPGetResourceParent @41
+ NPGetConnectionPerformance @49
+ NPGetResourceInformation @52
+ NPGetConnection3 @54
+
+; NPGetUser @16
+; NPGetReconnectFlags @53
+; I_SystemFocusDialog @15
diff --git a/src/WINNT/afsrdr/npdll/AFS_Npdll.c b/src/WINNT/afsrdr/npdll/AFS_Npdll.c
new file mode 100644
index 0000000000..56e9ef1663
--- /dev/null
+++ b/src/WINNT/afsrdr/npdll/AFS_Npdll.c
@@ -0,0 +1,3951 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
+ * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice,
+ * this list of conditions and the following disclaimer in the
+ * documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
+ * nor the names of their contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission from Kernel Drivers, LLC and Your File System, Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0500
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define AFS_DEBUG_TRACE 1
+
+#ifndef WNNC_NET_OPENAFS
+#define WNNC_NET_OPENAFS 0x00390000
+#endif
+
+#include "AFSUserDefines.h"
+#include "AFSUserIoctl.h"
+#include "AFSUserStructs.h"
+#include "AFSProvider.h"
+#include "AFS_Npdll.h"
+
+#include "stdio.h"
+
+#ifndef MAX_PATH
+#define MAX_PATH 260
+#endif
+
+#define SCRATCHSZ 1024
+
+//
+// Common information
+//
+
+ULONG _cdecl AFSDbgPrint( PWCHAR Format, ... );
+
+#define WNNC_DRIVER( major, minor ) ( major * 0x00010000 + minor )
+
+#define OPENAFS_PROVIDER_NAME L"OpenAFS Network"
+#define OPENAFS_PROVIDER_NAME_LENGTH 30
+
+#define MAX_PROVIDER_NAME_LENGTH 256
+
+static ULONG cbProviderNameLength = OPENAFS_PROVIDER_NAME_LENGTH;
+
+static wchar_t wszProviderName[MAX_PROVIDER_NAME_LENGTH+1] = OPENAFS_PROVIDER_NAME;
+
+static BOOL bProviderNameRead = FALSE;
+
+#define OPENAFS_SERVER_NAME L"AFS"
+#define OPENAFS_SERVER_NAME_LENGTH 6
+
+#define OPENAFS_SERVER_COMMENT L"AFS Root"
+#define OPENAFS_SERVER_COMMENT_LENGTH 16
+
+#define MAX_SERVER_NAME_LENGTH 30
+
+static ULONG cbServerNameLength = 0;
+
+static ULONG cbServerNameUNCLength = 0;
+
+static ULONG cbServerCommentLength = OPENAFS_SERVER_COMMENT_LENGTH;
+
+static wchar_t wszServerName[MAX_SERVER_NAME_LENGTH+1];
+
+static wchar_t wszServerNameUNC[MAX_SERVER_NAME_LENGTH+3];
+
+static wchar_t wszServerComment[] = OPENAFS_SERVER_COMMENT;
+
+static BOOL bServerNameRead = FALSE;
+
+LARGE_INTEGER
+AFSRetrieveAuthId( void);
+
+void
+ReadProviderNameString( void)
+{
+ HKEY hk;
+ DWORD code;
+ DWORD dwLen = 0;
+
+ if ( bProviderNameRead )
+ return;
+
+ code = RegOpenKeyExW( HKEY_LOCAL_MACHINE,
+ L"SYSTEM\\CurrentControlSet\\Services\\AFSRedirector\\NetworkProvider",
+ 0, KEY_QUERY_VALUE, &hk);
+
+ if ( code == ERROR_SUCCESS) {
+
+ dwLen = sizeof(wszProviderName);
+
+ code = RegQueryValueExW( hk, L"Name", NULL, NULL,
+ (LPBYTE) wszProviderName, &dwLen);
+
+ if ( code == ERROR_SUCCESS)
+ {
+
+ wszProviderName[MAX_PROVIDER_NAME_LENGTH] = '\0';
+
+ cbProviderNameLength = wcslen( wszProviderName) * sizeof( WCHAR);
+ }
+
+ RegCloseKey( hk);
+ }
+
+ bProviderNameRead = TRUE;
+}
+
+void
+ReadServerNameString( void)
+{
+ HKEY hk;
+ DWORD code;
+ DWORD dwLen = 0;
+
+ if ( bServerNameRead )
+ return;
+
+ code = RegOpenKeyExW( HKEY_LOCAL_MACHINE,
+ L"SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters",
+ 0, KEY_QUERY_VALUE, &hk);
+
+ if ( code == ERROR_SUCCESS) {
+
+ dwLen = sizeof(wszProviderName);
+
+ code = RegQueryValueExW( hk, L"NetbiosName", NULL, NULL,
+ (LPBYTE) wszServerName, &dwLen);
+
+ if ( code == ERROR_SUCCESS)
+ {
+
+ wszServerName[MAX_SERVER_NAME_LENGTH] = '\0';
+
+ cbServerNameLength = wcslen( wszServerName) * sizeof( WCHAR);
+
+ wszServerNameUNC[0] = wszServerNameUNC[1] = L'\\';
+
+ memcpy(&wszServerNameUNC[2], wszServerName, (cbServerNameLength + 1) * sizeof( WCHAR));
+
+ cbServerNameUNCLength = cbServerNameLength + 2 * sizeof( WCHAR);
+ }
+
+ RegCloseKey( hk);
+ }
+
+ bServerNameRead = TRUE;
+}
+
+
+
+/* returns TRUE if the file system is disabled or not installed */
+BOOL
+NPIsFSDisabled( void)
+{
+ HKEY hk;
+ DWORD code;
+ DWORD dwLen = 0;
+ DWORD dwStart = SERVICE_DISABLED;
+
+ code = RegOpenKeyExW( HKEY_LOCAL_MACHINE,
+ L"SYSTEM\\CurrentControlSet\\Services\\AFSRedirector",
+ 0, KEY_QUERY_VALUE, &hk);
+
+ if ( code != ERROR_SUCCESS)
+
+ return TRUE;
+
+
+ dwLen = sizeof(dwStart);
+
+ code = RegQueryValueExW( hk, L"Start", NULL, NULL,
+ (LPBYTE) &dwStart, &dwLen);
+
+ RegCloseKey( hk);
+
+ return ( dwStart == SERVICE_DISABLED);
+}
+
+
+#define try_return(S) { S; goto try_exit; }
+
+#define __Enter
+
+#define NOTHING
+
+typedef struct _UNICODE_STRING {
+ USHORT Length;
+ USHORT MaximumLength;
+ PWSTR Buffer;
+} UNICODE_STRING, *PUNICODE_STRING;
+
+HANDLE
+OpenRedirector( void);
+
+typedef struct _AFS_ENUM_CB
+{
+
+ DWORD CurrentIndex;
+
+ DWORD Scope;
+
+ DWORD Type;
+
+ WCHAR *RemoteName;
+
+} AFSEnumerationCB;
+
+
+//
+// Recursively evaluate drivestr to find the final
+// dos drive letter to which the source is mapped.
+//
+static BOOL
+DriveSubstitution(LPCWSTR drivestr, LPWSTR subststr, size_t substlen)
+{
+ WCHAR drive[3];
+ WCHAR device[MAX_PATH + 1];
+ HRESULT hr = S_OK;
+
+ memset( subststr, 0, substlen);
+ drive[0] = drivestr[0];
+ drive[1] = drivestr[1];
+ drive[2] = 0;
+
+ if ( QueryDosDevice(drive, device, MAX_PATH) )
+ {
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"DriveSubstitution QueryDosDevice %s [%s -> %s]\n",
+ drivestr,
+ drive,
+ device);
+#endif
+ if ( device[0] == L'\\' &&
+ device[1] == L'?' &&
+ device[2] == L'?' &&
+ device[3] == L'\\' &&
+ iswalpha(device[4]) &&
+ device[5] == L':')
+ {
+ drive[0] = device[4];
+ drive[1] = L':';
+ drive[2] = L'\0';
+
+ if ( !DriveSubstitution(drive, subststr, substlen) )
+ {
+
+ subststr[0] = drive[0];
+ subststr[1] = L':';
+ subststr[2] = L'\0';
+
+ }
+
+ hr = S_OK;
+
+ if ( device[6] )
+ {
+ hr = StringCchCat( subststr, substlen, &device[6]);
+ }
+ if ( SUCCEEDED(hr) && drivestr[2] )
+ {
+ hr = StringCchCat( subststr, substlen, &drivestr[2]);
+ }
+
+ if ( SUCCEEDED(hr) || hr == STRSAFE_E_INSUFFICIENT_BUFFER)
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"DriveSubstitution %s -> %s\n",
+ drivestr,
+ subststr);
+#endif
+ return TRUE;
+ }
+ }
+ else if ( device[0] == L'\\' &&
+ device[1] == L'?' &&
+ device[2] == L'?' &&
+ device[3] == L'\\' &&
+ device[4] == L'U' &&
+ device[5] == L'N' &&
+ device[6] == L'C' &&
+ device[7] == L'\\')
+ {
+
+ subststr[0] = L'\\';
+
+ hr = StringCbCopyN(&subststr[1], substlen - sizeof(WCHAR), &device[7], MAX_PATH);
+
+ if ( SUCCEEDED(hr) || hr == STRSAFE_E_INSUFFICIENT_BUFFER)
+ {
+ if ( drivestr[2] )
+ {
+ hr = StringCchCat( subststr, substlen, &drivestr[2]);
+ }
+ else
+ {
+ hr = S_OK;
+ }
+
+ if ( SUCCEEDED(hr) || hr == STRSAFE_E_INSUFFICIENT_BUFFER)
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"DriveSubstitution %s -> %s\n",
+ drivestr,
+ subststr);
+#endif
+ return TRUE;
+ }
+ }
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"DriveSubstitution StringCbCopyN 1 hr 0x%X\n",
+ hr);
+#endif
+ }
+ else if ( _wcsnicmp( AFS_RDR_DEVICE_NAME, device, sizeof( AFS_RDR_DEVICE_NAME) / sizeof( WCHAR) - 1) == 0)
+ {
+ //
+ // \Device\AFSRedirector\;X:\\afs\cellname
+ //
+
+ hr = StringCbCopyN( subststr, substlen,
+ &device[3 + sizeof( AFS_RDR_DEVICE_NAME) / sizeof( WCHAR)],
+ MAX_PATH * sizeof( WCHAR));
+
+ if ( SUCCEEDED(hr) || hr == STRSAFE_E_INSUFFICIENT_BUFFER)
+ {
+
+ if ( drivestr[2] )
+ {
+ hr = StringCchCat( subststr, substlen, &drivestr[2]);
+ }
+ else
+ {
+ hr = S_OK;
+ }
+
+ if ( SUCCEEDED(hr) || hr == STRSAFE_E_INSUFFICIENT_BUFFER)
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"DriveSubstitution %s -> %s\n",
+ drivestr,
+ subststr);
+#endif
+ return TRUE;
+ }
+ }
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"DriveSubstitution StringCbCopyN 2 hr 0x%X\n",
+ hr);
+#endif
+ }
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"DriveSubstitution no substitution or match %s !! %s\n",
+ drivestr,
+ device);
+#endif
+ }
+ else
+ {
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"DriveSubstitution QueryDosDevice failed %s gle 0x%X\n",
+ drivestr,
+ GetLastError());
+#endif
+ }
+
+
+
+ return FALSE;
+}
+
+
+static const WCHAR *
+NPGetCapsQueryString( DWORD nIndex)
+{
+ switch ( nIndex) {
+ case WNNC_SPEC_VERSION:
+ return L"WNNC_SPEC_VERSION";
+
+ case WNNC_NET_TYPE:
+ return L"WNNC_NET_TYPE";
+
+ case WNNC_DRIVER_VERSION:
+ return L"WNNC_DRIVER_VERSION";
+
+ case WNNC_USER:
+ return L"WNNC_USER";
+
+ case WNNC_CONNECTION:
+ return L"WNNC_CONNECTION";
+
+ case WNNC_DIALOG:
+ return L"WNNC_DIALOG";
+
+ case WNNC_ADMIN:
+ return L"WNNC_ADMIN";
+
+ case WNNC_ENUMERATION:
+ return L"WNNC_ENUMERATION";
+
+ case WNNC_START:
+ return L"WNNC_START";
+
+ case WNNC_CONNECTION_FLAGS:
+ return L"WNNC_CONNECTION_FLAGS";
+
+ default:
+ return L"UNKNOWN";
+ }
+}
+
+//
+// This is the only function which must be exported, everything else is optional
+//
+
+DWORD
+APIENTRY
+NPGetCaps( DWORD nIndex )
+{
+
+ DWORD rc = 0;
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetCaps Index %u %s\n", nIndex,
+ NPGetCapsQueryString( nIndex));
+#endif
+ switch( nIndex)
+ {
+ case WNNC_SPEC_VERSION:
+ {
+
+ rc = WNNC_SPEC_VERSION51;
+ break;
+ }
+
+ case WNNC_NET_TYPE:
+ {
+ rc = WNNC_NET_OPENAFS;
+ break;
+ }
+
+ case WNNC_DRIVER_VERSION:
+ {
+
+ rc = WNNC_DRIVER(1, 0);
+ break;
+ }
+
+ case WNNC_CONNECTION:
+ {
+
+ //
+ // No support for:
+ // WNNC_CON_GETPERFORMANCE
+ // WNNC_CON_DEFER
+ //
+
+ rc = WNNC_CON_GETCONNECTIONS |
+ WNNC_CON_CANCELCONNECTION |
+ WNNC_CON_ADDCONNECTION |
+ WNNC_CON_ADDCONNECTION3;
+
+ break;
+ }
+
+ case WNNC_ENUMERATION:
+ {
+ rc = WNNC_ENUM_LOCAL |
+ WNNC_ENUM_CONTEXT |
+ WNNC_ENUM_GLOBAL |
+ WNNC_ENUM_SHAREABLE;
+ break;
+ }
+
+ case WNNC_START:
+ {
+
+ rc = WNNC_WAIT_FOR_START;
+
+ break;
+ }
+
+ case WNNC_DIALOG:
+ {
+
+ //
+ // No support for:
+ // WNNC_DLG_DEVICEMODE
+ // WNNC_DLG_PROPERTYDIALOG
+ // WNNC_DLG_SEARCHDIALOG
+ // WNNC_DLG_PERMISSIONEDITOR
+ //
+
+ rc = WNNC_DLG_FORMATNETWORKNAME |
+ WNNC_DLG_GETRESOURCEINFORMATION |
+ WNNC_DLG_GETRESOURCEPARENT;
+
+ break;
+ }
+
+ case WNNC_USER:
+ {
+ //
+ // No support for:
+ // WNNC_USR_GETUSER
+ //
+
+ break;
+ }
+
+ case WNNC_ADMIN:
+ {
+ //
+ // No support for:
+ // WNNC_ADM_GETDIRECTORYTYPE
+ // WNNC_ADM_DIRECTORYNOTIFY
+ // used by the old File Manager
+ //
+ break;
+ }
+ }
+
+ return rc;
+}
+
+DWORD
+APIENTRY
+NPAddConnection( LPNETRESOURCE lpNetResource,
+ LPWSTR lpPassword,
+ LPWSTR lpUserName )
+{
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPAddConnection forwarding to NPAddConnection3\n");
+#endif
+ return NPAddConnection3( NULL, lpNetResource, lpPassword, lpUserName, 0 );
+}
+
+DWORD
+APIENTRY
+NPAddConnection3( HWND hwndOwner,
+ LPNETRESOURCE lpNetResource,
+ LPWSTR lpPassword,
+ LPWSTR lpUserName,
+ DWORD dwFlags )
+{
+
+ DWORD dwStatus = WN_SUCCESS;
+ WCHAR wchRemoteName[MAX_PATH+1];
+ WCHAR wchLocalName[3];
+ DWORD dwCopyBytes = 0;
+ AFSNetworkProviderConnectionCB *pConnectCB = NULL;
+ DWORD dwError = 0;
+ DWORD dwBufferSize = 0;
+ HANDLE hControlDevice = NULL;
+ HANDLE hToken = NULL;
+ LARGE_INTEGER liAuthId = {0,0};
+
+ __Enter
+ {
+ if ( NPIsFSDisabled())
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPAddConnection3 AFSRDFS is disabled, returning WN_BAD_NETNAME\n");
+#endif
+
+ return WN_BAD_NETNAME;
+ }
+
+ if ((lpNetResource->lpRemoteName == NULL) ||
+ (lpNetResource->lpRemoteName[0] != L'\\') ||
+ (lpNetResource->lpRemoteName[1] != L'\\') ||
+ ((lpNetResource->dwType != RESOURCETYPE_DISK) &&
+ (lpNetResource->dwType != RESOURCETYPE_ANY)))
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPAddConnection3 invalid input, returning WN_BAD_NETNAME\n");
+#endif
+ return WN_BAD_NETNAME;
+ }
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPAddConnection3 processing\n");
+#endif
+ if( lpNetResource->lpLocalName != NULL)
+ {
+
+ wchLocalName[0] = towupper(lpNetResource->lpLocalName[0]);
+ wchLocalName[1] = L':';
+ wchLocalName[2] = L'\0';
+ }
+
+ StringCchCopy(wchRemoteName, MAX_PATH+1, lpNetResource->lpRemoteName);
+ wchRemoteName[MAX_PATH] = L'\0';
+
+ //
+ // Allocate our buffer to pass to the redirector filter
+ //
+
+ dwBufferSize = sizeof( AFSNetworkProviderConnectionCB) + (wcslen( wchRemoteName) * sizeof( WCHAR));
+
+ pConnectCB = (AFSNetworkProviderConnectionCB *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufferSize);
+
+ if( pConnectCB == NULL)
+ {
+
+ try_return( dwStatus = WN_OUT_OF_MEMORY);
+ }
+
+ if( lpNetResource->lpLocalName != NULL)
+ {
+
+ pConnectCB->LocalName = towupper(wchLocalName[0]);
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPAddConnection3 Adding mapping for drive %s remote name %s\n",
+ wchLocalName,
+ wchRemoteName);
+#endif
+ }
+ else
+ {
+
+ pConnectCB->LocalName = L'\0';
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPAddConnection3 Adding mapping for NO drive remote name %s\n",
+ wchRemoteName);
+#endif
+ }
+
+ pConnectCB->Version = AFS_NETWORKPROVIDER_INTERFACE_VERSION_1;
+
+ pConnectCB->RemoteNameLength = wcslen( wchRemoteName) * sizeof( WCHAR);
+
+ memcpy( pConnectCB->RemoteName,
+ wchRemoteName,
+ pConnectCB->RemoteNameLength);
+
+ pConnectCB->Type = lpNetResource->dwType;
+
+ pConnectCB->AuthenticationId = AFSRetrieveAuthId();
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPAddConnection3 Retrieved authentication id %08lX-%08lX\n",
+ pConnectCB->AuthenticationId.HighPart,
+ pConnectCB->AuthenticationId.LowPart);
+#endif
+
+ hControlDevice = OpenRedirector();
+
+ if( hControlDevice == NULL)
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPAddConnection3 OpenRedirector failure, returning WN_NET_ERROR\n");
+#endif
+
+ try_return( dwStatus = WN_NET_ERROR);
+ }
+
+ dwError = DeviceIoControl( hControlDevice,
+ IOCTL_AFS_ADD_CONNECTION,
+ pConnectCB,
+ dwBufferSize,
+ &dwStatus,
+ sizeof( DWORD),
+ &dwCopyBytes,
+ NULL);
+
+ if( !dwError)
+ {
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPAddConnection3 Failed to add connection to file system %d\n", GetLastError());
+#endif
+ try_return( dwStatus = WN_OUT_OF_MEMORY);
+ }
+
+ //
+ // The status returned from the driver will indicate how it was handled
+ //
+
+ if( dwStatus == WN_SUCCESS &&
+ lpNetResource->lpLocalName != NULL)
+ {
+
+ WCHAR TempBuf[MAX_PATH+1];
+
+ if( !QueryDosDeviceW( wchLocalName,
+ TempBuf,
+ MAX_PATH+1))
+ {
+
+ if( GetLastError() != ERROR_FILE_NOT_FOUND)
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPAddConnection3 QueryDosDeviceW failed with file not found\n");
+#endif
+ NPCancelConnection( wchLocalName, TRUE);
+
+ dwStatus = ERROR_ALREADY_ASSIGNED;
+ }
+ else
+ {
+
+ UNICODE_STRING uniConnectionName;
+ UNICODE_STRING uniDeviceName;
+
+ uniDeviceName.Length = (wcslen( AFS_RDR_DEVICE_NAME) * sizeof( WCHAR));
+ uniDeviceName.MaximumLength = uniDeviceName.Length;
+ uniDeviceName.Buffer = AFS_RDR_DEVICE_NAME;
+
+ //
+ // Create a symbolic link object to the device we are redirecting
+ //
+
+ uniConnectionName.MaximumLength = (USHORT)( uniDeviceName.Length +
+ pConnectCB->RemoteNameLength +
+ 8 + // Local name and \;
+ sizeof(WCHAR)); // Space for NULL-termination.
+
+ //
+ // Don't include NULL-termination.
+ //
+
+ uniConnectionName.Length = uniConnectionName.MaximumLength - sizeof(WCHAR);
+
+ uniConnectionName.Buffer = LocalAlloc( LMEM_ZEROINIT,
+ uniConnectionName.MaximumLength);
+
+ if( uniConnectionName.Buffer == NULL)
+ {
+
+ try_return( dwStatus = GetLastError());
+ }
+
+ CopyMemory( uniConnectionName.Buffer,
+ uniDeviceName.Buffer,
+ uniDeviceName.Length);
+
+ StringCchCatW( uniConnectionName.Buffer,
+ uniConnectionName.MaximumLength,
+ L"\\;" );
+
+ StringCchCatW( uniConnectionName.Buffer,
+ uniConnectionName.MaximumLength,
+ wchLocalName);
+
+ StringCchCatW( uniConnectionName.Buffer,
+ uniConnectionName.MaximumLength,
+ wchRemoteName);
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPAddConnection3 DefineDosDevice Local %s connection name %s\n",
+ wchLocalName,
+ uniConnectionName.Buffer);
+#endif
+
+ if( !DefineDosDeviceW( DDD_RAW_TARGET_PATH |
+ DDD_NO_BROADCAST_SYSTEM,
+ wchLocalName,
+ uniConnectionName.Buffer))
+ {
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPAddConnection3 Failed to assign drive\n");
+#endif
+ dwStatus = GetLastError();
+ }
+ else
+ {
+
+ dwStatus = WN_SUCCESS;
+ }
+
+ LocalFree( uniConnectionName.Buffer);
+ }
+ }
+ else
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPAddConnection3 QueryDosDeviceW %Z already existed\n", TempBuf);
+#endif
+ NPCancelConnection( wchLocalName, TRUE);
+
+ dwStatus = ERROR_ALREADY_ASSIGNED;
+ }
+ }
+
+try_exit:
+
+ if ( hControlDevice != NULL)
+ {
+
+ CloseHandle( hControlDevice);
+ }
+
+ if( pConnectCB != NULL)
+ {
+
+ HeapFree( GetProcessHeap( ), 0, (PVOID) pConnectCB);
+ }
+ }
+
+ return dwStatus;
+}
+
+DWORD
+APIENTRY
+NPCancelConnection( LPWSTR lpName,
+ BOOL fForce)
+{
+
+ WCHAR wchRemoteName[MAX_PATH+1];
+ DWORD dwRemoteNameLength = (MAX_PATH+1) * sizeof(WCHAR);
+ DWORD dwStatus = WN_NOT_CONNECTED;
+ DWORD dwCopyBytes = 0;
+ AFSNetworkProviderConnectionCB *pConnectCB = NULL;
+ AFSCancelConnectionResultCB stCancelConn;
+ DWORD dwError = 0;
+ DWORD dwBufferSize = 0;
+ BOOL bLocalName = TRUE;
+ HANDLE hControlDevice = NULL;
+ WCHAR *pwchLocalName = NULL;
+
+ __Enter
+ {
+
+ if ( NPIsFSDisabled())
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPCancelConnection AFSRDFS is disabled, returning WN_NOT_CONNECTED\n");
+#endif
+
+ try_return( dwStatus = WN_NOT_CONNECTED);
+ }
+
+ if( *lpName == L'\\' &&
+ *(lpName + 1) == L'\\')
+ {
+
+ bLocalName = FALSE;
+ }
+
+ if( bLocalName)
+ {
+
+ //
+ // Get the remote name for the connection, if we are handling it
+ //
+
+ dwStatus = NPGetConnection( lpName,
+ wchRemoteName,
+ &dwRemoteNameLength);
+
+ if( dwStatus != WN_SUCCESS ||
+ dwRemoteNameLength == 0)
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPCancelConnection Status 0x%x NameLength %u, returning WN_NOT_CONNECTED\n",
+ dwStatus, dwRemoteNameLength);
+#endif
+ try_return( dwStatus = WN_NOT_CONNECTED);
+ }
+ }
+ else
+ {
+
+ StringCchCopyW( wchRemoteName, MAX_PATH+1, lpName);
+
+ dwRemoteNameLength = (wcslen( wchRemoteName) * sizeof( WCHAR));
+ }
+
+ wchRemoteName[ dwRemoteNameLength/sizeof( WCHAR)] = L'\0';
+
+ dwBufferSize = sizeof( AFSNetworkProviderConnectionCB) + dwRemoteNameLength;
+
+ pConnectCB = (AFSNetworkProviderConnectionCB *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufferSize);
+
+ if( pConnectCB == NULL)
+ {
+
+ try_return( dwStatus = WN_OUT_OF_MEMORY);
+ }
+
+ if( bLocalName)
+ {
+
+ pConnectCB->LocalName = towupper(lpName[0]);
+ }
+ else
+ {
+
+ pConnectCB->LocalName = L'\0';
+ }
+
+ pConnectCB->RemoteNameLength = (USHORT)dwRemoteNameLength;
+
+ StringCchCopyW( pConnectCB->RemoteName,
+ MAX_PATH+1,
+ wchRemoteName);
+
+ pConnectCB->Version = AFS_NETWORKPROVIDER_INTERFACE_VERSION_1;
+
+ pConnectCB->AuthenticationId = AFSRetrieveAuthId();
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPCancelConnection Retrieved authentication id %08lX-%08lX\n",
+ pConnectCB->AuthenticationId.HighPart,
+ pConnectCB->AuthenticationId.LowPart);
+#endif
+
+ hControlDevice = OpenRedirector();
+
+ if( hControlDevice == NULL)
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPCancelConnection OpenRedirector failure, returning WN_NET_ERROR\n");
+#endif
+
+ try_return( dwStatus = WN_NET_ERROR);
+ }
+
+ memset( &stCancelConn,
+ '\0',
+ sizeof( AFSCancelConnectionResultCB));
+
+ dwError = DeviceIoControl( hControlDevice,
+ IOCTL_AFS_CANCEL_CONNECTION,
+ pConnectCB,
+ dwBufferSize,
+ &stCancelConn,
+ sizeof( AFSCancelConnectionResultCB),
+ &dwCopyBytes,
+ NULL);
+
+ if( !dwError)
+ {
+#ifdef AFS_DEBUG_TRACE
+ DWORD gle = GetLastError();
+
+ AFSDbgPrint( L"NPCancelConnection Failed to cancel connection to file system - gle 0x%x\n", gle);
+#endif
+ try_return( dwStatus = WN_NOT_CONNECTED);
+ }
+
+ dwStatus = stCancelConn.Status;
+
+#ifdef AFS_DEBUG_TRACE
+
+ AFSDbgPrint( L"NPCancelConnection Cancel connection to file system - Name %s Status %08lX\n",
+ lpName,
+ dwStatus);
+#endif
+
+ if( dwStatus == WN_SUCCESS &&
+ ( bLocalName ||
+ stCancelConn.LocalName != L'\0'))
+ {
+
+ UNICODE_STRING uniConnectionName;
+ UNICODE_STRING uniDeviceName;
+
+ uniDeviceName.Length = (wcslen( AFS_RDR_DEVICE_NAME) * sizeof( WCHAR));
+ uniDeviceName.MaximumLength = uniDeviceName.Length;
+ uniDeviceName.Buffer = AFS_RDR_DEVICE_NAME;
+
+ //
+ // Create a symbolic link object to the device we are redirecting
+ //
+
+ uniConnectionName.MaximumLength = (USHORT)( uniDeviceName.Length +
+ dwRemoteNameLength +
+ 8 + // Local name and \;
+ sizeof(WCHAR)); // Space for NULL-termination.
+
+ //
+ // Don't include NULL-termination.
+ //
+
+ uniConnectionName.Length = uniConnectionName.MaximumLength - sizeof(WCHAR);
+
+ uniConnectionName.Buffer = LocalAlloc( LMEM_ZEROINIT,
+ uniConnectionName.MaximumLength);
+
+ if( uniConnectionName.Buffer == NULL)
+ {
+
+ try_return( dwStatus = GetLastError());
+ }
+
+ CopyMemory( uniConnectionName.Buffer,
+ uniDeviceName.Buffer,
+ uniDeviceName.Length);
+
+ StringCchCatW( uniConnectionName.Buffer,
+ uniConnectionName.MaximumLength,
+ L"\\;" );
+
+ if( !bLocalName)
+ {
+
+ WCHAR wchLocalName[ 3];
+
+ wchLocalName[ 0] = stCancelConn.LocalName;
+
+ wchLocalName[ 1] = L':';
+
+ wchLocalName[ 2] = L'\0';
+
+ StringCchCatW( uniConnectionName.Buffer,
+ uniConnectionName.MaximumLength,
+ wchLocalName);
+
+ pwchLocalName = wchLocalName;
+ }
+ else
+ {
+
+ StringCchCatW( uniConnectionName.Buffer,
+ uniConnectionName.MaximumLength,
+ lpName);
+
+ pwchLocalName = lpName;
+ }
+
+ StringCchCatW( uniConnectionName.Buffer,
+ uniConnectionName.MaximumLength,
+ wchRemoteName);
+
+ if( !DefineDosDevice( DDD_REMOVE_DEFINITION | DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE,
+ pwchLocalName,
+ uniConnectionName.Buffer))
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ DWORD gle = GetLastError();
+
+ AFSDbgPrint( L"NPCancelConnection Failed to cancel connection to system - gle 0x%x Name %s connection %wZ\n",
+ gle,
+ pwchLocalName,
+ &uniConnectionName);
+#endif
+ }
+ else
+ {
+#ifdef AFS_DEBUG_TRACE
+
+ AFSDbgPrint( L"NPCancelConnection Canceled connection to system - Name %s connection %wZ\n",
+ pwchLocalName,
+ &uniConnectionName);
+#endif
+ }
+ }
+
+try_exit:
+
+ if ( hControlDevice != NULL)
+ {
+
+ CloseHandle( hControlDevice);
+ }
+
+
+ if( pConnectCB != NULL)
+ {
+
+ HeapFree( GetProcessHeap( ), 0, (PVOID) pConnectCB);
+ }
+
+ }
+
+ return dwStatus;
+}
+
+DWORD
+APIENTRY
+NPGetConnection( LPWSTR lpLocalName,
+ LPWSTR lpRemoteName,
+ LPDWORD lpBufferSize)
+{
+
+ DWORD dwStatus = WN_NOT_CONNECTED;
+ WCHAR wchLocalName[3];
+ WCHAR wchSubstName[MAX_PATH + 1];
+ AFSNetworkProviderConnectionCB *pConnectCB = NULL;
+ DWORD dwError = 0;
+ DWORD dwBufferSize = 0;
+ HANDLE hControlDevice = NULL;
+ DWORD dwPassedSize;
+
+ __Enter
+ {
+
+ if ( NPIsFSDisabled())
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection AFSRDFS is disabled, returning WN_NOT_CONNECTED\n");
+#endif
+
+ try_return( dwStatus = WN_NOT_CONNECTED);
+ }
+
+ if( lstrlen( lpLocalName) == 0)
+ {
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection No local name, returning WN_BAD_LOCALNAME\n");
+#endif
+ try_return( dwStatus = WN_BAD_LOCALNAME);
+ }
+
+ if ( lpBufferSize == NULL)
+ {
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection No output size, returning WN_BAD_LOCALNAME\n");
+#endif
+ try_return( dwStatus = WN_BAD_VALUE);
+ }
+
+ dwPassedSize = *lpBufferSize;
+
+ if ( !DriveSubstitution( lpLocalName, wchSubstName, sizeof( wchSubstName)))
+ {
+ wchLocalName[0] = towupper(lpLocalName[0]);
+ wchLocalName[1] = L':';
+ wchLocalName[2] = L'\0';
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection Requesting connection for %s\n",
+ wchLocalName);
+#endif
+ }
+ else
+ {
+ ReadServerNameString();
+
+ if ( wchSubstName[0] != L'\\' &&
+ wchSubstName[1] == L':')
+ {
+
+ wchLocalName[0] = towupper(wchSubstName[0]);
+ wchLocalName[1] = L':';
+ wchLocalName[2] = L'\0';
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection Requesting connection for drive substitution %s -> %s\n",
+ wchSubstName,
+ wchLocalName);
+#endif
+ }
+ else if ( _wcsnicmp( wchSubstName, wszServerNameUNC, cbServerNameUNCLength / sizeof( WCHAR)) == 0 &&
+ ( wchSubstName[cbServerNameUNCLength / sizeof( WCHAR)] == L'\\' ||
+ wchSubstName[cbServerNameUNCLength / sizeof( WCHAR)] == 0))
+ {
+ HRESULT hr;
+ WCHAR *pwch;
+ DWORD dwCount = 0;
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection drive substitution %s is AFS\n",
+ wchSubstName);
+#endif
+
+ if ( lpRemoteName == NULL ||
+ dwPassedSize == 0)
+ {
+
+ *lpBufferSize = wcslen( wchSubstName) * sizeof( WCHAR) + sizeof( WCHAR);
+
+ try_return( dwStatus = WN_MORE_DATA);
+
+ }
+
+ hr = StringCbCopyN(lpRemoteName, *lpBufferSize, wchSubstName, sizeof( wchSubstName));
+
+ if ( SUCCEEDED(hr))
+ {
+
+ for ( dwCount = 0, pwch = lpRemoteName; *pwch; pwch++ )
+ {
+ if ( *pwch == L'\\' )
+ {
+ dwCount++;
+
+ if ( dwCount == 4)
+ {
+ *pwch = L'\0';
+
+ break;
+ }
+ }
+
+ }
+
+ *lpBufferSize = wcslen( lpRemoteName) * sizeof( WCHAR) + sizeof( WCHAR);
+
+ try_return( dwStatus = WN_SUCCESS);
+ }
+ else if ( hr == STRSAFE_E_INSUFFICIENT_BUFFER)
+ {
+
+ *lpBufferSize = wcslen( wchSubstName) * sizeof( WCHAR) + sizeof( WCHAR);
+
+ for ( dwCount = 0, pwch = lpRemoteName; *pwch; pwch++ )
+ {
+ if ( *pwch == L'\\' )
+ {
+ dwCount++;
+
+ if ( dwCount == 4)
+ {
+ *pwch = L'\0';
+
+ *lpBufferSize = wcslen( lpRemoteName) * sizeof( WCHAR) + sizeof( WCHAR);
+
+ try_return( dwStatus = WN_SUCCESS);
+ }
+ }
+
+ }
+
+ try_return( dwStatus = WN_MORE_DATA);
+ }
+ else
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection StringCbCopyN failure 0x%X\n",
+ hr);
+#endif
+ try_return( dwStatus = WN_NET_ERROR);
+ }
+ }
+ else
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection drive substitution %s is not AFS\n",
+ wchSubstName);
+#endif
+ try_return( dwStatus = WN_NOT_CONNECTED);
+ }
+ }
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection Requesting connection for %s\n",
+ wchLocalName);
+#endif
+
+ dwBufferSize = 0x1000;
+
+ pConnectCB = (AFSNetworkProviderConnectionCB *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufferSize);
+
+ if( pConnectCB == NULL)
+ {
+
+ try_return( dwStatus = WN_OUT_OF_MEMORY);
+ }
+
+ pConnectCB->LocalName = towupper(wchLocalName[0]);
+
+ pConnectCB->RemoteNameLength = 0;
+
+ pConnectCB->Version = AFS_NETWORKPROVIDER_INTERFACE_VERSION_1;
+
+ pConnectCB->AuthenticationId = AFSRetrieveAuthId();
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection Retrieved authentication id %08lX-%08lX\n",
+ pConnectCB->AuthenticationId.HighPart,
+ pConnectCB->AuthenticationId.LowPart);
+#endif
+
+ hControlDevice = OpenRedirector();
+
+ if( hControlDevice == NULL)
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection OpenRedirector failure, returning WN_NET_ERROR\n");
+#endif
+
+ try_return( dwStatus = WN_NET_ERROR);
+ }
+
+ dwError = DeviceIoControl( hControlDevice,
+ IOCTL_AFS_GET_CONNECTION,
+ pConnectCB,
+ dwBufferSize,
+ pConnectCB,
+ dwBufferSize,
+ lpBufferSize,
+ NULL);
+
+ if( !dwError)
+ {
+#ifdef AFS_DEBUG_TRACE
+ DWORD gle = GetLastError();
+
+ AFSDbgPrint( L"NPGetConnection Failed to get connection from file system for local %s gle 0x%x\n",
+ wchLocalName, gle);
+#endif
+ try_return( dwStatus = WN_NOT_CONNECTED);
+ }
+
+ //
+ // IOCTL_AFS_GET_CONNECTION returns a counted string
+ //
+
+ if( lpRemoteName == NULL ||
+ *lpBufferSize + sizeof( WCHAR) > dwPassedSize)
+ {
+
+ *lpBufferSize += sizeof( WCHAR);
+
+ try_return( dwStatus = WN_MORE_DATA);
+ }
+
+ memcpy( lpRemoteName,
+ (void *)pConnectCB,
+ *lpBufferSize);
+
+ lpRemoteName[ *lpBufferSize/sizeof( WCHAR)] = L'\0';
+
+ *lpBufferSize += sizeof( WCHAR);
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection local %s remote %s\n",
+ wchLocalName,
+ lpRemoteName);
+#endif
+ dwStatus = WN_SUCCESS;
+
+try_exit:
+
+ if ( hControlDevice != NULL)
+ {
+
+ CloseHandle( hControlDevice);
+ }
+
+ if( pConnectCB != NULL)
+ {
+
+ HeapFree( GetProcessHeap( ), 0, (PVOID) pConnectCB);
+ }
+ }
+
+ return dwStatus;
+}
+
+DWORD
+APIENTRY
+NPGetConnection3( IN LPCWSTR lpLocalName,
+ IN DWORD dwLevel,
+ OUT LPVOID lpBuffer,
+ IN OUT LPDWORD lpBufferSize)
+{
+
+ DWORD dwStatus = WN_NOT_CONNECTED;
+ WCHAR wchLocalName[3];
+ WCHAR wchSubstName[MAX_PATH + 1];
+ AFSNetworkProviderConnectionCB *pConnectCB = NULL;
+ DWORD dwError = 0;
+ DWORD dwBufferSize = 0;
+ HANDLE hControlDevice = NULL;
+ DWORD dwPassedSize;
+ DWORD *pConnectState =(DWORD *)lpBuffer;
+
+ __Enter
+ {
+
+ if ( NPIsFSDisabled())
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection3 AFSRDFS is disabled, returning WN_NOT_CONNECTED\n");
+#endif
+
+ try_return( dwStatus = WN_NOT_CONNECTED);
+ }
+
+ if( lstrlen( lpLocalName) == 0)
+ {
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection3 No local name, returning WN_BAD_LOCALNAME\n");
+#endif
+ try_return( dwStatus = WN_BAD_LOCALNAME);
+ }
+
+ //
+ // LanMan NPGetConnection3 only responds to level 1
+ //
+
+ if ( dwLevel != 0x1)
+ {
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection3 Level 0x%X returning WN_BAD_LEVEL\n", dwLevel);
+#endif
+ try_return( dwStatus = WN_BAD_LEVEL);
+ }
+
+ if ( lpBufferSize == NULL)
+ {
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection3 No output size, returning WN_BAD_VALUE\n");
+#endif
+ try_return( dwStatus = WN_BAD_VALUE);
+ }
+
+ dwPassedSize = *lpBufferSize;
+
+ if ( dwPassedSize == 0 ||
+ lpBuffer == NULL)
+ {
+
+ *lpBufferSize = sizeof( DWORD);
+
+ try_return( dwStatus = WN_MORE_DATA);
+ }
+
+ if ( !DriveSubstitution( lpLocalName, wchSubstName, sizeof( wchSubstName)))
+ {
+ wchLocalName[0] = towupper(lpLocalName[0]);
+ wchLocalName[1] = L':';
+ wchLocalName[2] = L'\0';
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection3 Requesting connection for %s level 0x%X\n",
+ wchLocalName,
+ dwLevel);
+#endif
+ }
+ else
+ {
+
+ ReadServerNameString();
+
+ if ( wchSubstName[0] != L'\\' &&
+ wchSubstName[1] == L':')
+ {
+
+ wchLocalName[0] = towupper(wchSubstName[0]);
+ wchLocalName[1] = L':';
+ wchLocalName[2] = L'\0';
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection3 Requesting connection for drive substitution %s -> %s level 0x%x\n",
+ wchSubstName,
+ wchLocalName,
+ dwLevel);
+#endif
+ }
+ else if ( _wcsnicmp( wchSubstName, wszServerNameUNC, cbServerNameUNCLength / sizeof( WCHAR)) == 0 &&
+ ( wchSubstName[cbServerNameUNCLength / sizeof( WCHAR)] == L'\\' ||
+ wchSubstName[cbServerNameUNCLength / sizeof( WCHAR)] == 0))
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection3 drive substitution %s is AFS return connected\n",
+ wchSubstName);
+#endif
+ *pConnectState = WNGETCON_CONNECTED;
+
+ *lpBufferSize = sizeof( DWORD);
+
+ try_return( dwStatus = WN_SUCCESS);
+ }
+ else
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection3 drive substitution %s is not AFS return not connected\n",
+ wchSubstName);
+#endif
+ try_return( dwStatus = WN_NOT_CONNECTED);
+ }
+ }
+
+ dwBufferSize = 0x1000;
+
+ pConnectCB = (AFSNetworkProviderConnectionCB *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufferSize);
+
+ if( pConnectCB == NULL)
+ {
+
+ try_return( dwStatus = WN_OUT_OF_MEMORY);
+ }
+
+ pConnectCB->LocalName = towupper(wchLocalName[0]);
+
+ pConnectCB->RemoteNameLength = 0;
+
+ pConnectCB->Version = AFS_NETWORKPROVIDER_INTERFACE_VERSION_1;
+
+ pConnectCB->AuthenticationId = AFSRetrieveAuthId();
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection3 Retrieved authentication id %08lX-%08lX\n",
+ pConnectCB->AuthenticationId.HighPart,
+ pConnectCB->AuthenticationId.LowPart);
+#endif
+
+ hControlDevice = OpenRedirector();
+
+ if( hControlDevice == NULL)
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection3 OpenRedirector failure, returning WN_NET_ERROR\n");
+#endif
+
+ try_return( dwStatus = WN_NET_ERROR);
+ }
+
+ dwError = DeviceIoControl( hControlDevice,
+ IOCTL_AFS_GET_CONNECTION,
+ pConnectCB,
+ dwBufferSize,
+ pConnectCB,
+ dwBufferSize,
+ &dwBufferSize,
+ NULL);
+
+ if( !dwError)
+ {
+#ifdef AFS_DEBUG_TRACE
+ DWORD gle = GetLastError();
+
+ AFSDbgPrint( L"NPGetConnection3 Failed to get connection from file system for local %s gle 0x%x\n",
+ wchLocalName, gle);
+#endif
+ try_return( dwStatus = WN_NOT_CONNECTED);
+ }
+
+ *lpBufferSize = sizeof( DWORD);
+
+ if( sizeof( DWORD) > dwPassedSize)
+ {
+
+ try_return( dwStatus = WN_MORE_DATA);
+ }
+
+ *pConnectState = WNGETCON_CONNECTED;
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnection3 local %s connect-state 0x%x\n",
+ wchLocalName,
+ *pConnectState);
+#endif
+ dwStatus = WN_SUCCESS;
+
+try_exit:
+
+ if ( hControlDevice != NULL)
+ {
+
+ CloseHandle( hControlDevice);
+ }
+
+ if( pConnectCB != NULL)
+ {
+
+ HeapFree( GetProcessHeap( ), 0, (PVOID) pConnectCB);
+ }
+ }
+
+ return dwStatus;
+}
+
+DWORD
+APIENTRY
+NPGetConnectionPerformance( LPCWSTR lpRemoteName,
+ LPNETCONNECTINFOSTRUCT lpNetConnectInfo)
+{
+
+ DWORD dwReturn = WN_SUCCESS;
+ AFSNetworkProviderConnectionCB *pConnectCB = NULL;
+ DWORD dwBufferSize = 0;
+ HANDLE hControlDevice = NULL;
+ DWORD dwError = 0;
+
+ __Enter
+ {
+
+ if ( NPIsFSDisabled())
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetConnectionPerformance AFSRDFS is disabled, returning WN_BAD_NETNAME\n");
+#endif
+
+ return WN_NO_NETWORK;
+ }
+
+ AFSDbgPrint( L"NPGetConnectionPerformance Entry for remote connection %S\n",
+ lpRemoteName);
+
+ dwBufferSize = 0x1000;
+
+ pConnectCB = (AFSNetworkProviderConnectionCB *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufferSize);
+
+ if( pConnectCB == NULL)
+ {
+ try_return( dwReturn = WN_OUT_OF_MEMORY);
+ }
+
+ pConnectCB->RemoteNameLength = wcslen( lpRemoteName) * sizeof( WCHAR);
+
+ StringCbCopy( pConnectCB->RemoteName,
+ dwBufferSize - sizeof(AFSNetworkProviderConnectionCB),
+ lpRemoteName);
+
+ pConnectCB->Version = AFS_NETWORKPROVIDER_INTERFACE_VERSION_1;
+
+ pConnectCB->AuthenticationId = AFSRetrieveAuthId();
+
+ hControlDevice = OpenRedirector();
+
+ if( hControlDevice == NULL)
+ {
+ AFSDbgPrint( L"NPGetConnectionPerformance OpenRedirector failure, returning WN_NET_ERROR\n");
+
+ try_return( dwReturn = WN_NET_ERROR);
+ }
+
+ dwError = DeviceIoControl( hControlDevice,
+ IOCTL_AFS_GET_CONNECTION_INFORMATION,
+ pConnectCB,
+ dwBufferSize,
+ pConnectCB,
+ dwBufferSize,
+ &dwBufferSize,
+ NULL);
+
+ if( !dwError)
+ {
+#ifdef AFS_DEBUG_TRACE
+ DWORD gle = GetLastError();
+
+ AFSDbgPrint( L"NPGetConnectionPerformance Failed to get connection info from file system for remote %S gle 0x%x\n",
+ lpRemoteName,
+ gle);
+#endif
+ try_return( dwReturn = WN_NOT_CONNECTED);
+ }
+
+ lpNetConnectInfo->dwFlags = WNCON_DYNAMIC;
+
+ lpNetConnectInfo->dwSpeed = 500;
+
+ lpNetConnectInfo->dwDelay = 0;
+
+ lpNetConnectInfo->dwOptDataSize = 0x1000;
+
+ AFSDbgPrint( L"NPGetConnectionPerformance Successfully returned information for remote connection %S\n",
+ lpRemoteName);
+
+try_exit:
+
+ if ( hControlDevice != NULL)
+ {
+ CloseHandle( hControlDevice);
+ }
+
+ if( pConnectCB != NULL)
+ {
+ HeapFree( GetProcessHeap( ), 0, (PVOID) pConnectCB);
+ }
+ }
+
+ return dwReturn;
+}
+
+static LPCWSTR
+GetUsageString( DWORD dwUsage)
+{
+ static WCHAR Buffer[128] = L"";
+ //
+ // RESOURCEUSAGE_CONNECTABLE 0x00000001
+ // RESOURCEUSAGE_CONTAINER 0x00000002
+ // RESOURCEUSAGE_NOLOCALDEVICE 0x00000004
+ // RESOURCEUSAGE_SIBLING 0x00000008
+ // RESOURCEUSAGE_ATTACHED 0x00000010
+ // RESOURCEUSAGE_ALL (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED)
+ // RESOURCEUSAGE_RESERVED 0x80000000
+ //
+
+ Buffer[0] = L'\0';
+
+ if ( dwUsage == RESOURCEUSAGE_ALL )
+ {
+ return L"ALL";
+ }
+
+ if ( dwUsage == 0 )
+ {
+ return L"NONE";
+ }
+
+ if ( dwUsage & RESOURCEUSAGE_CONNECTABLE )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"CONNECTABLE|");
+ }
+
+ if ( dwUsage & RESOURCEUSAGE_CONTAINER )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"CONTAINER|");
+ }
+
+ if ( dwUsage & RESOURCEUSAGE_NOLOCALDEVICE )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"NOLOCALDEVICE|");
+ }
+
+ if ( dwUsage & RESOURCEUSAGE_SIBLING )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"SIBLING|");
+ }
+
+ if ( dwUsage & RESOURCEUSAGE_ATTACHED )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"ATTACHED|");
+ }
+
+ if ( dwUsage & RESOURCEUSAGE_RESERVED )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"RESERVED|");
+ }
+
+ if ( dwUsage & ~(RESOURCEUSAGE_ALL|RESOURCEUSAGE_NOLOCALDEVICE|RESOURCEUSAGE_SIBLING|RESOURCEUSAGE_RESERVED) )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"UNKNOWN|");
+ }
+
+ Buffer[lstrlen(Buffer)-1] = L'\0';
+
+ return Buffer;
+}
+
+static LPCWSTR
+GetTypeString( DWORD dwType)
+{
+ static WCHAR Buffer[128] = L"";
+
+ //
+ // RESOURCETYPE_ANY 0x00000000
+ // RESOURCETYPE_DISK 0x00000001
+ // RESOURCETYPE_PRINT 0x00000002
+ // RESOURCETYPE_RESERVED 0x00000008
+ // RESOURCETYPE_UNKNOWN 0xFFFFFFFF
+ //
+
+ Buffer[0] = L'\0';
+
+ if ( dwType == RESOURCETYPE_ANY )
+ {
+ return L"ANY";
+ }
+
+ if ( dwType == RESOURCETYPE_UNKNOWN )
+ {
+ return L"UNKNOWN";
+ }
+
+ if ( dwType & RESOURCETYPE_DISK )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"DISK|");
+ }
+
+ if ( dwType & RESOURCETYPE_PRINT )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"PRINT|");
+ }
+
+ if ( dwType & RESOURCETYPE_RESERVED )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"RESERVED|");
+ }
+
+ if ( dwType & ~(RESOURCETYPE_DISK|RESOURCETYPE_PRINT|RESOURCETYPE_RESERVED) )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"UNKNOWN|");
+ }
+
+ Buffer[lstrlen(Buffer)-1] = L'\0';
+
+ return Buffer;
+}
+
+static LPCWSTR
+GetScopeString( DWORD dwScope)
+{
+ static WCHAR Buffer[128] = L"";
+
+ //
+ // RESOURCE_CONNECTED 0x00000001
+ // RESOURCE_GLOBALNET 0x00000002
+ // RESOURCE_REMEMBERED 0x00000003
+ // RESOURCE_RECENT 0x00000004
+ // RESOURCE_CONTEXT 0x00000005
+ //
+
+ Buffer[0] = L'\0';
+
+ if ( dwScope == RESOURCE_CONNECTED )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"CONNECTED|");
+ }
+
+ if ( dwScope == RESOURCE_GLOBALNET )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"GLOBALNET|");
+ }
+
+ if ( dwScope == RESOURCE_REMEMBERED )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"REMEMBERED|");
+ }
+
+ if ( dwScope == RESOURCE_RECENT )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"RECENT|");
+ }
+
+ if ( dwScope == RESOURCE_CONTEXT )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"CONTEXT|");
+ }
+
+ if ( dwScope & ~(RESOURCE_CONNECTED|RESOURCE_GLOBALNET|RESOURCE_REMEMBERED|RESOURCE_RECENT|RESOURCE_CONTEXT) )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"UNKNOWN|");
+ }
+
+ Buffer[lstrlen(Buffer)-1] = L'\0';
+
+ return Buffer;
+}
+
+static LPCWSTR
+GetDisplayString( DWORD dwDisplay)
+{
+ //
+ // RESOURCEDISPLAYTYPE_GENERIC 0x00000000
+ // RESOURCEDISPLAYTYPE_DOMAIN 0x00000001
+ // RESOURCEDISPLAYTYPE_SERVER 0x00000002
+ // RESOURCEDISPLAYTYPE_SHARE 0x00000003
+ // RESOURCEDISPLAYTYPE_FILE 0x00000004
+ // RESOURCEDISPLAYTYPE_GROUP 0x00000005
+ // RESOURCEDISPLAYTYPE_NETWORK 0x00000006
+ // RESOURCEDISPLAYTYPE_ROOT 0x00000007
+ // RESOURCEDISPLAYTYPE_SHAREADMIN 0x00000008
+ // RESOURCEDISPLAYTYPE_DIRECTORY 0x00000009
+ // RESOURCEDISPLAYTYPE_TREE 0x0000000A
+ // RESOURCEDISPLAYTYPE_NDSCONTAINER 0x0000000B
+ //
+
+ switch ( dwDisplay ) {
+ case RESOURCEDISPLAYTYPE_GENERIC:
+ return L"GENERIC";
+ case RESOURCEDISPLAYTYPE_DOMAIN:
+ return L"DOMAIN";
+ case RESOURCEDISPLAYTYPE_SERVER:
+ return L"SERVER";
+ case RESOURCEDISPLAYTYPE_SHARE:
+ return L"SHARE";
+ case RESOURCEDISPLAYTYPE_FILE:
+ return L"FILE";
+ case RESOURCEDISPLAYTYPE_GROUP:
+ return L"GROUP";
+ case RESOURCEDISPLAYTYPE_NETWORK:
+ return L"NETWORK";
+ case RESOURCEDISPLAYTYPE_ROOT:
+ return L"ROOT";
+ case RESOURCEDISPLAYTYPE_SHAREADMIN:
+ return L"SHAREADMIN";
+ case RESOURCEDISPLAYTYPE_DIRECTORY:
+ return L"DIRECTORY";
+ case RESOURCEDISPLAYTYPE_TREE:
+ return L"TREE";
+ case RESOURCEDISPLAYTYPE_NDSCONTAINER:
+ return L"NDSCONTAINER";
+ default:
+ return L"UNKNOWN";
+ }
+}
+
+DWORD
+APIENTRY
+NPOpenEnum( DWORD dwScope,
+ DWORD dwType,
+ DWORD dwUsage,
+ LPNETRESOURCE lpNetResource,
+ LPHANDLE lphEnum )
+{
+
+ DWORD dwStatus = WN_SUCCESS;
+ AFSEnumerationCB *pEnumCB = NULL;
+
+#ifdef AFS_DEBUG_TRACE
+ if ( lpNetResource == NULL)
+ {
+ AFSDbgPrint( L"NPOpenEnum Scope %s Type %s Usage %s NetResource: (Null)\n",
+ GetScopeString(dwScope), GetTypeString(dwType), GetUsageString(dwUsage));
+ }
+ else
+ {
+ AFSDbgPrint( L"NPOpenEnum Scope %s Type %s Usage %s NetResource (0x%p): Scope %s Type %s Display %s Usage %s Local %s Remote \"%s\" Comment \"%s\"\n",
+ GetScopeString(dwScope),
+ GetTypeString(dwType),
+ GetUsageString(dwUsage),
+ lpNetResource,
+ GetScopeString(lpNetResource->dwScope),
+ GetTypeString(lpNetResource->dwType),
+ GetDisplayString(lpNetResource->dwDisplayType),
+ GetUsageString(lpNetResource->dwUsage),
+ lpNetResource->lpLocalName,
+ lpNetResource->lpRemoteName,
+ lpNetResource->lpComment);
+ }
+#endif
+
+ if ( dwUsage == 0 )
+ {
+ dwUsage = RESOURCEUSAGE_ALL;
+ }
+
+#if 0
+ if ( dwType == 0 || dwType == RESOURCEUSAGE_ATTACHED)
+ {
+ dwType |= RESOURCETYPE_DISK | RESOURCETYPE_PRINT;
+ }
+#endif
+
+ *lphEnum = HeapAlloc( GetProcessHeap( ), HEAP_ZERO_MEMORY, sizeof( AFSEnumerationCB));
+
+ if( *lphEnum == NULL)
+ {
+
+ return WN_OUT_OF_MEMORY;
+ }
+
+ pEnumCB = (AFSEnumerationCB *)*lphEnum;
+
+ pEnumCB->CurrentIndex = 0;
+
+ pEnumCB->Type = dwType;
+
+ switch( dwScope )
+ {
+ case RESOURCE_CONNECTED:
+ {
+
+ pEnumCB->Scope = RESOURCE_CONNECTED;
+
+ break;
+ }
+
+ case RESOURCE_CONTEXT:
+ {
+
+ pEnumCB->Scope = RESOURCE_CONTEXT;
+
+ break;
+ }
+
+ case RESOURCE_GLOBALNET:
+ {
+
+ if( lpNetResource != NULL &&
+ lpNetResource->lpRemoteName != NULL)
+ {
+
+ pEnumCB->RemoteName = (WCHAR *)HeapAlloc( GetProcessHeap( ), HEAP_ZERO_MEMORY, 0x1000);
+
+ if( pEnumCB->RemoteName == NULL)
+ {
+
+ dwStatus = WN_OUT_OF_MEMORY;
+ HeapFree( GetProcessHeap( ), 0, (PVOID) *lphEnum );
+ *lphEnum = NULL;
+ }
+ else
+ {
+
+ StringCbCopy( pEnumCB->RemoteName,
+ 0x1000,
+ lpNetResource->lpRemoteName);
+
+ }
+ }
+
+ pEnumCB->Scope = RESOURCE_GLOBALNET;
+
+ break;
+ }
+
+ default:
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPOpenEnum Processing (Scope %s 0x%x) Type %s Usage %s, returning WN_NOT_SUPPORTED\n",
+ GetScopeString(dwScope), dwScope, GetTypeString(dwType), GetUsageString(dwUsage));
+#endif
+
+ dwStatus = WN_NOT_SUPPORTED;
+ HeapFree( GetProcessHeap( ), 0, (PVOID) *lphEnum );
+ *lphEnum = NULL;
+
+ break;
+ }
+
+ return dwStatus;
+}
+
+
+DWORD
+APIENTRY
+NPEnumResource( HANDLE hEnum,
+ LPDWORD lpcCount,
+ LPVOID lpBuffer,
+ LPDWORD lpBufferSize)
+{
+
+ DWORD dwStatus = WN_NO_MORE_ENTRIES; //WN_SUCCESS;
+ ULONG dwCopyBytes;
+ ULONG EntriesCopied;
+ ULONG EntriesRequested;
+ ULONG dwIndex;
+ LPNETRESOURCE pNetResource;
+ ULONG SpaceNeeded;
+ ULONG SpaceAvailable;
+ PWCHAR StringZone;
+ AFSNetworkProviderConnectionCB *pConnectionCB = NULL;
+ void *pConnectionCBBase = NULL;
+ DWORD dwError = 0;
+ UNICODE_STRING uniRemoteName;
+ HANDLE hControlDevice = NULL;
+ AFSEnumerationCB *pEnumCB = (AFSEnumerationCB *)hEnum;
+
+ __Enter
+ {
+
+ if ( lpBufferSize == NULL)
+ {
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPEnumResource No output size, returning WN_BAD_VALUE\n");
+#endif
+ try_return( dwStatus = WN_BAD_VALUE);
+ }
+
+ ReadProviderNameString();
+
+ pNetResource = (LPNETRESOURCE) lpBuffer;
+ SpaceAvailable = *lpBufferSize;
+ EntriesRequested = *lpcCount;
+ *lpcCount = EntriesCopied = 0;
+ StringZone = (PWCHAR) ((char *)lpBuffer + *lpBufferSize);
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPEnumResource Processing Remote name %s Scope %s Type %s Usage %s Index %d SpaceAvailable 0x%lX RequestedEntries %lu\n",
+ pEnumCB->RemoteName ? pEnumCB->RemoteName : L"(Null)",
+ GetScopeString(pEnumCB->Scope),
+ GetTypeString(pEnumCB->Type),
+ GetUsageString(pEnumCB->Type),
+ pEnumCB->CurrentIndex,
+ SpaceAvailable,
+ EntriesRequested);
+#endif
+
+ if ( NPIsFSDisabled())
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPEnumResource AFSRDFS is disabled, returning WN_NO_MORE_ENTRIES\n");
+#endif
+
+ try_return( dwStatus = WN_NO_MORE_ENTRIES);
+ }
+
+ pConnectionCB = (AFSNetworkProviderConnectionCB *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 0x1000);
+
+ if( pConnectionCB == NULL)
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPEnumResource Out of Memory\n");
+#endif
+
+ try_return( dwStatus = WN_OUT_OF_MEMORY);
+ }
+
+ pConnectionCBBase = (void *)pConnectionCB;
+
+ hControlDevice = OpenRedirector();
+
+ if( hControlDevice == NULL)
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPEnumResource OpenRedirector failure, returning WN_NET_ERROR\n");
+#endif
+
+ try_return( dwStatus = WN_NET_ERROR);
+ }
+
+ //
+ // Handle the special cases here
+ // 0. Provider Network Root
+ // 1. Server Root
+ //
+
+#if 0
+ if ( pEnumCB->Scope == RESOURCE_GLOBALNET)
+ {
+
+ ReadServerNameString();
+
+ if ( pEnumCB->CurrentIndex == 0 &&
+ pEnumCB->RemoteName == NULL)
+ {
+
+ // Determine the space needed for this entry...
+
+ SpaceNeeded = 2 * ( cbProviderNameLength + sizeof( WCHAR));
+
+ uniRemoteName.Length = (USHORT)cbProviderNameLength;
+ uniRemoteName.MaximumLength = uniRemoteName.Length;
+ uniRemoteName.Buffer = wszProviderName;
+
+ if( SpaceNeeded + sizeof( NETRESOURCE) > SpaceAvailable)
+ {
+
+ *lpBufferSize = SpaceNeeded + sizeof( NETRESOURCE);
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPEnumResource Request MORE_DATA for entry %s Len %d\n",
+ &uniRemoteName,
+ *lpBufferSize);
+#endif
+ try_return( dwStatus = WN_MORE_DATA);
+ }
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPEnumResource Processing Entry %wZ\n",
+ &uniRemoteName);
+#endif
+
+ SpaceAvailable -= (SpaceNeeded + sizeof( NETRESOURCE));
+
+ pNetResource->dwScope = RESOURCE_GLOBALNET;
+ pNetResource->dwType = RESOURCETYPE_ANY;
+ pNetResource->dwDisplayType = RESOURCEDISPLAYTYPE_NETWORK;
+ pNetResource->dwUsage = RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_RESERVED;
+
+ // setup string area at opposite end of buffer
+ StringZone = (PWCHAR)( (PBYTE) StringZone - SpaceNeeded);
+
+ pNetResource->lpLocalName = NULL;
+
+ // copy remote name
+ pNetResource->lpRemoteName = StringZone;
+
+ StringCbCopy( StringZone,
+ cbProviderNameLength + sizeof( WCHAR),
+ wszProviderName);
+
+ StringZone += cbProviderNameLength / sizeof(WCHAR) + 1;
+
+ pNetResource->lpComment = NULL;
+
+ // copy provider name
+ pNetResource->lpProvider = StringZone;
+ StringCbCopy( StringZone,
+ cbProviderNameLength + sizeof( WCHAR),
+ wszProviderName);
+
+ StringZone += cbProviderNameLength / sizeof( WCHAR) + 1;
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPEnumResource Entry (0x%p) Scope %s Type %s Display %s Usage %s Local %s Remote \"%s\" Comment \"%s\"\n",
+ pNetResource,
+ GetScopeString(pNetResource->dwScope),
+ GetTypeString(pNetResource->dwType),
+ GetDisplayString(pNetResource->dwDisplayType),
+ GetUsageString(pNetResource->dwUsage),
+ pNetResource->lpLocalName,
+ pNetResource->lpRemoteName,
+ pNetResource->lpComment);
+#endif
+
+ // setup the new end of buffer
+ StringZone = (PWCHAR)( (PBYTE) StringZone - SpaceNeeded);
+
+ EntriesCopied++;
+
+ pNetResource++;
+
+ // do not change the index since we did not query the redirector
+ pEnumCB->CurrentIndex = 0;
+
+ // remember that we returned the provider name
+ pEnumCB->RemoteName = (WCHAR *)HeapAlloc( GetProcessHeap( ), HEAP_ZERO_MEMORY, 0x1000);
+
+ if( pEnumCB->RemoteName == NULL)
+ {
+
+ try_return( dwStatus = WN_OUT_OF_MEMORY);
+ }
+ else
+ {
+
+ StringCbCopy( pEnumCB->RemoteName,
+ 0x1000,
+ wszProviderName);
+ }
+ }
+
+ if ( pEnumCB->CurrentIndex == 0 &&
+ lstrlen( pEnumCB->RemoteName) == cbProviderNameLength / sizeof( WCHAR) &&
+ _wcsnicmp( pEnumCB->RemoteName, wszProviderName, cbProviderNameLength / sizeof( WCHAR)) == 0 &&
+ EntriesCopied < EntriesRequested)
+ {
+
+ //
+ // After the network provider entry comes the server entry
+ //
+
+ // Determine the space needed for this entry...
+
+ SpaceNeeded = cbProviderNameLength + cbServerNameUNCLength + cbServerCommentLength + 3 * sizeof( WCHAR);
+
+ uniRemoteName.Length = (USHORT)cbServerNameUNCLength;
+ uniRemoteName.MaximumLength = uniRemoteName.Length;
+ uniRemoteName.Buffer = wszServerNameUNC;
+
+ if( SpaceNeeded + sizeof( NETRESOURCE) > SpaceAvailable)
+ {
+
+ *lpBufferSize = SpaceNeeded + sizeof( NETRESOURCE);
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPEnumResource Request MORE_DATA for entry %s Len %d\n",
+ &uniRemoteName,
+ *lpBufferSize);
+#endif
+ try_return( dwStatus = WN_MORE_DATA);
+ }
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPEnumResource Processing Entry %wZ\n",
+ &uniRemoteName);
+#endif
+
+ SpaceAvailable -= (SpaceNeeded + sizeof( NETRESOURCE));
+
+ pNetResource->dwScope = 0;
+ pNetResource->dwType = RESOURCETYPE_ANY;
+ pNetResource->dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
+ pNetResource->dwUsage = RESOURCEUSAGE_CONTAINER;
+
+ // setup string area at opposite end of buffer
+ StringZone = (PWCHAR)( (PBYTE) StringZone - SpaceNeeded);
+
+ pNetResource->lpLocalName = NULL;
+
+ // copy remote name
+ pNetResource->lpRemoteName = StringZone;
+
+ StringCbCopy( StringZone,
+ cbServerNameUNCLength + sizeof( WCHAR),
+ wszServerNameUNC);
+
+ StringZone += cbServerNameUNCLength / sizeof(WCHAR) + 1;
+
+ // copy comment
+ pNetResource->lpComment = StringZone;
+
+ StringCbCopy( StringZone,
+ cbServerCommentLength + sizeof( WCHAR),
+ wszServerComment);
+
+ StringZone += cbServerCommentLength / sizeof( WCHAR) + 1;
+
+ // copy provider name
+ pNetResource->lpProvider = StringZone;
+ StringCbCopy( StringZone,
+ cbProviderNameLength + sizeof( WCHAR),
+ wszProviderName);
+
+ StringZone += cbProviderNameLength / sizeof( WCHAR) + 1;
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPEnumResource Entry (0x%p) Scope %s Type %s Display %s Usage %s Local %s Remote \"%s\" Comment \"%s\"\n",
+ pNetResource,
+ GetScopeString(pNetResource->dwScope),
+ GetTypeString(pNetResource->dwType),
+ GetDisplayString(pNetResource->dwDisplayType),
+ GetUsageString(pNetResource->dwUsage),
+ pNetResource->lpLocalName,
+ pNetResource->lpRemoteName,
+ pNetResource->lpComment);
+#endif
+
+ // setup the new end of buffer
+ StringZone = (PWCHAR)( (PBYTE) StringZone - SpaceNeeded);
+
+ EntriesCopied++;
+
+ pNetResource++;
+
+ // do not update the index because we did not query the redirector
+ pEnumCB->CurrentIndex = 0;
+
+ // remember that we returned the server
+ StringCbCopy( pEnumCB->RemoteName,
+ 0x1000,
+ wszServerNameUNC);
+ }
+ }
+#endif
+
+ //
+ // Setup what we are going to ask for
+ //
+
+ pConnectionCB->Scope = pEnumCB->Scope;
+
+ pConnectionCB->Type = pEnumCB->Type;
+
+ pConnectionCB->CurrentIndex = pEnumCB->CurrentIndex;
+
+ pConnectionCB->Version = AFS_NETWORKPROVIDER_INTERFACE_VERSION_1;
+
+ //
+ // If this is a RESOURCE_GLOBALNET enumeration then pass down the remote name if
+ // there is one
+ //
+
+ pConnectionCB->RemoteNameLength = 0;
+
+ if( pEnumCB->Scope == RESOURCE_GLOBALNET &&
+ pEnumCB->RemoteName != NULL)
+ {
+
+ pConnectionCB->RemoteNameLength = wcslen( pEnumCB->RemoteName) * sizeof( WCHAR);
+
+ StringCbCopy( pConnectionCB->RemoteName,
+ (0x1000 - sizeof(AFSNetworkProviderConnectionCB)) + sizeof(WCHAR),
+ pEnumCB->RemoteName);
+ }
+
+ pConnectionCB->AuthenticationId = AFSRetrieveAuthId();
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPEnumResource Retrieved authentication id %08lX-%08lX\n",
+ pConnectionCB->AuthenticationId.HighPart,
+ pConnectionCB->AuthenticationId.LowPart);
+#endif
+
+ dwError = DeviceIoControl( hControlDevice,
+ IOCTL_AFS_LIST_CONNECTIONS,
+ pConnectionCB,
+ 0x1000,
+ pConnectionCB,
+ 0x1000,
+ &dwCopyBytes,
+ NULL);
+
+ if( !dwError)
+ {
+#ifdef AFS_DEBUG_TRACE
+ DWORD gle = GetLastError();
+
+ AFSDbgPrint( L"NPEnumResource Failed to list connections from file system - gle 0x%x\n",
+ gle);
+#endif
+ try_return( dwStatus = WN_NOT_CONNECTED);
+ }
+
+ if( dwCopyBytes == 0)
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPEnumResource No More Entries\n");
+#endif
+ try_return( dwStatus = WN_NO_MORE_ENTRIES);
+ }
+
+ dwIndex = pEnumCB->CurrentIndex;
+
+ while( EntriesCopied < EntriesRequested)
+ {
+
+ uniRemoteName.Length = (USHORT)pConnectionCB->RemoteNameLength;
+ uniRemoteName.MaximumLength = uniRemoteName.Length;
+ uniRemoteName.Buffer = pConnectionCB->RemoteName;
+
+ // Determine the space needed for this entry...
+
+ SpaceNeeded = 0;
+
+ if( pConnectionCB->LocalName != 0)
+ {
+
+ SpaceNeeded += 3 * sizeof(WCHAR); // local name
+ }
+
+ SpaceNeeded += pConnectionCB->RemoteNameLength + sizeof( WCHAR); // remote name
+
+ if( pConnectionCB->CommentLength > 0)
+ {
+
+ SpaceNeeded += pConnectionCB->CommentLength + sizeof( WCHAR); // comment
+ }
+
+ SpaceNeeded += cbProviderNameLength + sizeof( WCHAR); // provider name
+
+ if( SpaceNeeded + sizeof( NETRESOURCE) > SpaceAvailable)
+ {
+
+ if (EntriesCopied == 0) {
+
+ dwStatus = WN_MORE_DATA;
+
+ *lpBufferSize = SpaceNeeded + sizeof( NETRESOURCE);
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPEnumResource Request MORE_DATA for entry %s Len %d\n",
+ &uniRemoteName,
+ *lpBufferSize);
+#endif
+
+ } else {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPEnumResource Return SUCCESS but more entries Index %d\n",
+ dwIndex);
+#endif
+
+ dwStatus = WN_SUCCESS;
+ }
+
+ break;
+ }
+
+ SpaceAvailable -= (SpaceNeeded + sizeof( NETRESOURCE));
+
+ pNetResource->dwScope = pConnectionCB->Scope;
+ pNetResource->dwType = pConnectionCB->Type;
+
+ pNetResource->dwDisplayType = pConnectionCB->DisplayType;
+
+ if ( pNetResource->dwType == RESOURCETYPE_ANY &&
+ pNetResource->dwDisplayType == RESOURCEDISPLAYTYPE_SHARE)
+ {
+
+ pNetResource->dwType = RESOURCETYPE_DISK;
+ }
+ pNetResource->dwUsage = pConnectionCB->Usage;
+
+ // setup string area at opposite end of buffer
+ StringZone = (PWCHAR)( (PBYTE) StringZone - SpaceNeeded);
+
+ // copy local name
+ if( pConnectionCB->LocalName != 0)
+ {
+
+ pNetResource->lpLocalName = StringZone;
+ *StringZone++ = towupper(pConnectionCB->LocalName);
+ *StringZone++ = L':';
+ *StringZone++ = L'\0';
+ }
+ else
+ {
+
+ pNetResource->lpLocalName = NULL;
+ }
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPEnumResource Processing Entry %wZ\n",
+ &uniRemoteName);
+#endif
+
+ // copy remote name
+ pNetResource->lpRemoteName = StringZone;
+
+ CopyMemory( StringZone,
+ pConnectionCB->RemoteName,
+ pConnectionCB->RemoteNameLength);
+
+ StringZone += (pConnectionCB->RemoteNameLength / sizeof(WCHAR));
+
+ *StringZone++ = L'\0';
+
+ // copy comment
+ if( pConnectionCB->CommentLength > 0)
+ {
+
+ pNetResource->lpComment = StringZone;
+
+ CopyMemory( StringZone,
+ (void *)((char *)pConnectionCB + pConnectionCB->CommentOffset),
+ pConnectionCB->CommentLength);
+
+ StringZone += (pConnectionCB->CommentLength / sizeof(WCHAR));
+
+ *StringZone++ = L'\0';
+ }
+ else
+ {
+
+ pNetResource->lpComment = NULL;
+ }
+
+ // copy provider name
+ pNetResource->lpProvider = StringZone;
+ StringCbCopy( StringZone,
+ cbProviderNameLength + sizeof( WCHAR),
+ wszProviderName);
+
+ StringZone += (cbProviderNameLength / sizeof( WCHAR) + 1);
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPEnumResource Entry (0x%p) Scope %s Type %s Display %s Usage %s Local %s Remote \"%s\" Comment \"%s\"\n",
+ pNetResource,
+ GetScopeString(pNetResource->dwScope),
+ GetTypeString(pNetResource->dwType),
+ GetDisplayString(pNetResource->dwDisplayType),
+ GetUsageString(pNetResource->dwUsage),
+ pNetResource->lpLocalName,
+ pNetResource->lpRemoteName,
+ pNetResource->lpComment);
+#endif
+
+ // setup the new end of buffer
+ StringZone = (PWCHAR)( (PBYTE) StringZone - SpaceNeeded);
+
+ EntriesCopied++;
+
+ pNetResource++;
+
+ dwIndex++;
+
+ dwCopyBytes -= FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
+ pConnectionCB->RemoteNameLength +
+ pConnectionCB->CommentLength;
+
+ if( dwCopyBytes == 0)
+ {
+
+ dwStatus = WN_SUCCESS;
+
+ break;
+ }
+
+ pConnectionCB = (AFSNetworkProviderConnectionCB *)((char *)pConnectionCB +
+ FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
+ pConnectionCB->RemoteNameLength +
+ pConnectionCB->CommentLength);
+ }
+
+ *lpcCount = EntriesCopied;
+
+ // update entry index
+ pEnumCB->CurrentIndex = dwIndex;
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPEnumResource Completed Count %d Index %d\n",
+ EntriesCopied,
+ dwIndex);
+#endif
+
+try_exit:
+
+ if ( hControlDevice != NULL)
+ {
+
+ CloseHandle( hControlDevice);
+ }
+
+ if( pConnectionCBBase != NULL)
+ {
+
+ HeapFree( GetProcessHeap( ), 0, (PVOID) pConnectionCBBase);
+ }
+ }
+
+ return dwStatus;
+}
+
+/*++
+
+Routine Description:
+
+ This routine closes the handle for enumeration of resources.
+
+Arguments:
+
+ hEnum - the enumeration handle
+
+Return Value:
+
+ WN_SUCCESS if successful, otherwise the appropriate error
+
+Notes:
+
+ The sample only supports the notion of enumerating connected shares
+
+--*/
+
+DWORD APIENTRY
+NPCloseEnum( HANDLE hEnum )
+{
+
+ AFSEnumerationCB *pEnumCB = (AFSEnumerationCB *)hEnum;
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPCloseEnum\n");
+#endif
+
+ if( pEnumCB->RemoteName != NULL)
+ {
+
+ HeapFree( GetProcessHeap( ), 0, (PVOID) pEnumCB->RemoteName);
+ }
+
+ HeapFree( GetProcessHeap( ), 0, (PVOID) hEnum );
+
+ return WN_SUCCESS;
+}
+
+DWORD APIENTRY
+NPGetResourceParent( LPNETRESOURCE lpNetResource,
+ LPVOID lpBuffer,
+ LPDWORD lpBufferSize )
+{
+
+ DWORD dwStatus = WN_ACCESS_DENIED;
+ WCHAR *pwchRemoteName = NULL, *pwchSearch = NULL, *pwchSystem = NULL;
+ LPNETRESOURCE lpOutResource = (LPNETRESOURCE) lpBuffer;
+
+ if ( lpNetResource == NULL)
+ {
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetResourceParent NULL NETRESOURCE\n");
+#endif
+ return WN_MORE_DATA;
+ }
+
+ if( lpNetResource->lpRemoteName == NULL)
+ {
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetResourceParent NULL NETRESOURCE\n");
+#endif
+ return WN_BAD_NETNAME;
+ }
+
+ if ( lpNetResource->dwType != 0 &&
+ lpNetResource->dwType != RESOURCETYPE_DISK)
+ {
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetResourceParent Bad dwType\n");
+#endif
+ return WN_BAD_VALUE;
+ }
+
+ if ( lpBufferSize == NULL )
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetResourceParent Null lpBufferSize\n");
+#endif
+ return WN_BAD_VALUE;
+ }
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetResourceParent For remote name %s\n",
+ lpNetResource->lpRemoteName);
+#endif
+
+ pwchRemoteName = lpNetResource->lpRemoteName;
+
+ pwchSearch = pwchRemoteName + (wcslen( pwchRemoteName) - 1);
+
+ while( pwchSearch != pwchRemoteName)
+ {
+
+ if( *pwchSearch == L'\\')
+ {
+
+ *pwchSearch = L'\0';
+
+ break;
+ }
+
+ pwchSearch--;
+ }
+
+ if( pwchSearch != pwchRemoteName)
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetResourceParent Processing parent %s\n",
+ lpNetResource->lpRemoteName);
+#endif
+
+ dwStatus = NPGetResourceInformation( lpNetResource,
+ lpBuffer,
+ lpBufferSize,
+ &pwchSystem);
+ }
+ else
+ {
+ if ( lpOutResource == NULL ||
+ *lpBufferSize < sizeof( NETRESOURCE) )
+ {
+ *lpBufferSize = sizeof( NETRESOURCE);
+
+ return WN_MORE_DATA;
+ }
+
+ memset( lpOutResource, 0, sizeof( NETRESOURCE));
+
+ return WN_SUCCESS;
+
+ }
+
+ return dwStatus;
+}
+
+DWORD APIENTRY
+NPGetResourceInformation( LPNETRESOURCE lpNetResource,
+ LPVOID lpBuffer,
+ LPDWORD lpBufferSize,
+ LPWSTR *lplpSystem )
+{
+
+ DWORD dwStatus = WN_NOT_CONNECTED;
+ AFSNetworkProviderConnectionCB *pConnectCB = NULL;
+ DWORD dwError = 0;
+ DWORD dwBufferSize = 0;
+ HANDLE hControlDevice = NULL;
+ NETRESOURCE *pNetResource = (NETRESOURCE *)lpBuffer;
+ PWCHAR pStringZone = NULL;
+ UNICODE_STRING uniRemoteName;
+ DWORD ulRequiredLen = 0;
+ DWORD dwPassedSize;
+
+
+ __Enter
+ {
+ if ( lplpSystem)
+ {
+ *lplpSystem = NULL;
+ }
+
+ ReadProviderNameString();
+
+ if ( NPIsFSDisabled())
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetResourceInformation AFSRDFS is disabled, returning WN_BAD_NETNAME\n");
+#endif
+
+ try_return( dwStatus = WN_BAD_NETNAME);
+ }
+
+ if ( lpNetResource == NULL ||
+ lpBufferSize == NULL )
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetResourceInformaton Null lpNetResource or lpBufferSize\n");
+#endif
+ return WN_BAD_VALUE;
+ }
+
+ if( lpNetResource->lpRemoteName == NULL)
+ {
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetResourceInformation No resource name\n");
+#endif
+
+ try_return( dwStatus = WN_NOT_CONNECTED);
+ }
+
+ dwPassedSize = *lpBufferSize;
+
+ dwBufferSize = 0x1000;
+
+ pConnectCB = (AFSNetworkProviderConnectionCB *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufferSize);
+
+ if( pConnectCB == NULL)
+ {
+
+ try_return( dwStatus = WN_OUT_OF_MEMORY);
+ }
+
+ pConnectCB->RemoteNameLength = wcslen( lpNetResource->lpRemoteName) * sizeof( WCHAR);
+
+ StringCbCopy( pConnectCB->RemoteName,
+ dwBufferSize - sizeof(AFSNetworkProviderConnectionCB),
+ lpNetResource->lpRemoteName);
+
+ pConnectCB->Version = AFS_NETWORKPROVIDER_INTERFACE_VERSION_1;
+
+ pConnectCB->AuthenticationId = AFSRetrieveAuthId();
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetResourceInformation Retrieved authentication id %08lX-%08lX\n",
+ pConnectCB->AuthenticationId.HighPart,
+ pConnectCB->AuthenticationId.LowPart);
+#endif
+
+ hControlDevice = OpenRedirector();
+
+ if( hControlDevice == NULL)
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetResourceInformation OpenRedirector failure, returning WN_NET_ERROR\n");
+#endif
+
+ try_return( dwStatus = WN_NET_ERROR);
+ }
+
+ dwError = DeviceIoControl( hControlDevice,
+ IOCTL_AFS_GET_CONNECTION_INFORMATION,
+ pConnectCB,
+ dwBufferSize,
+ pConnectCB,
+ dwBufferSize,
+ lpBufferSize,
+ NULL);
+
+ if( !dwError)
+ {
+#ifdef AFS_DEBUG_TRACE
+ DWORD gle = GetLastError();
+
+ AFSDbgPrint( L"NPGetResourceInformation Failed to get connection info from file system for local %s gle 0x%x\n",
+ lpNetResource->lpRemoteName, gle);
+#endif
+ try_return( dwStatus = WN_BAD_NETNAME);
+ }
+
+ uniRemoteName.Length = (USHORT)pConnectCB->RemoteNameLength;
+ uniRemoteName.MaximumLength = uniRemoteName.Length;
+ uniRemoteName.Buffer = pConnectCB->RemoteName;
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetResourceInformation For remote name %wZ Scope %08lX Type %08lX Usage %08lX\n",
+ &uniRemoteName,
+ pConnectCB->Scope,
+ pConnectCB->Type,
+ pConnectCB->Usage);
+#endif
+
+ // Determine the space needed for this entry...
+
+ ulRequiredLen = sizeof( NETRESOURCE);
+
+ ulRequiredLen += pConnectCB->RemoteNameLength + sizeof( WCHAR);
+
+ ulRequiredLen += pConnectCB->CommentLength + sizeof( WCHAR);
+
+ ulRequiredLen += cbProviderNameLength + sizeof( WCHAR);
+
+ ulRequiredLen += pConnectCB->RemainingPathLength + sizeof( WCHAR);
+
+ if( pNetResource == NULL ||
+ ulRequiredLen > dwPassedSize)
+ {
+
+ *lpBufferSize = ulRequiredLen;
+
+ try_return( dwStatus = WN_MORE_DATA);
+ }
+
+ pStringZone = (PWCHAR) ((char *)lpBuffer + sizeof( NETRESOURCE));
+
+ pNetResource->dwScope = 0 /* pConnectCB->Scope*/;
+ pNetResource->dwType = 0 /* pConnectCB->Type */;
+
+ pNetResource->dwDisplayType = pConnectCB->DisplayType;
+
+ pNetResource->dwUsage = pConnectCB->Usage;
+
+ pNetResource->lpLocalName = NULL;
+
+ // copy remote name
+ pNetResource->lpRemoteName = pStringZone;
+
+ CopyMemory( pStringZone,
+ pConnectCB->RemoteName,
+ pConnectCB->RemoteNameLength);
+
+ pStringZone += (pConnectCB->RemoteNameLength / sizeof(WCHAR));
+
+ *pStringZone++ = L'\0';
+
+ // copy comment
+ pNetResource->lpComment = pStringZone;
+
+ CopyMemory( pStringZone,
+ (void *)((char *)pConnectCB + pConnectCB->CommentOffset),
+ pConnectCB->CommentLength);
+
+ pStringZone += (pConnectCB->CommentLength / sizeof(WCHAR));
+
+ *pStringZone++ = L'\0';
+
+ // copy remaining path
+ if (pConnectCB->RemainingPathLength > 0)
+ {
+ *lplpSystem = pStringZone;
+
+ CopyMemory( pStringZone,
+ (void *)((char *)pConnectCB + pConnectCB->RemainingPathOffset),
+ pConnectCB->RemainingPathLength);
+
+ pStringZone += (pConnectCB->RemainingPathLength / sizeof(WCHAR));
+
+ *pStringZone++ = L'\0';
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetResourceInformation For remote name %s returning remaining path %s\n",
+ pNetResource->lpRemoteName,
+ *lplpSystem);
+#endif
+ }
+
+ // copy provider name
+ pNetResource->lpProvider = pStringZone;
+
+ StringCbCopy( pStringZone,
+ cbProviderNameLength + sizeof( WCHAR),
+ wszProviderName);
+
+ pStringZone += (cbProviderNameLength / sizeof( WCHAR) + 1);
+
+ *lpBufferSize = ulRequiredLen;
+
+ dwStatus = WN_SUCCESS;
+
+try_exit:
+
+ if ( hControlDevice != NULL)
+ {
+
+ CloseHandle( hControlDevice);
+ }
+
+ if( pConnectCB != NULL)
+ {
+
+ HeapFree( GetProcessHeap( ), 0, (PVOID) pConnectCB);
+ }
+ }
+
+ return dwStatus;
+}
+
+static VOID
+SeparateRemainingPath( WCHAR * lpConnectionName, WCHAR **lppRemainingPath)
+{
+ WCHAR *pwch;
+ WCHAR wch1, wch2;
+ DWORD dwCount;
+
+ //
+ // at this point the lpConnectionName contains the full name. We need to
+ // truncate it to \\server\share and move the remaining path back one position.
+ //
+
+ for ( pwch = lpConnectionName, dwCount = 0; *pwch; pwch++)
+ {
+ if ( *pwch == L'\\')
+ {
+ dwCount++;
+ }
+
+ if ( dwCount == 4)
+ {
+ break;
+ }
+ }
+
+ if (*pwch == L'\\')
+ {
+ //
+ // Found the remaining path that must be moved
+ //
+
+ *lppRemainingPath = pwch + 1;
+
+ *pwch++ = 0;
+
+ //
+ // Find the end
+ //
+ for ( ; *pwch; pwch++);
+
+ //
+ // and work backwards moving the string
+ // and then make sure that there is at least
+ // a path separator.
+ //
+
+ *(pwch + 1) = 0;
+
+ for ( ;pwch > *lppRemainingPath; pwch--)
+ {
+ *pwch = *(pwch - 1);
+ }
+
+ *pwch = L'\\';
+ }
+}
+
+DWORD APIENTRY
+NPGetUniversalName( LPCWSTR lpLocalPath,
+ DWORD dwInfoLevel,
+ LPVOID lpBuffer,
+ LPDWORD lpBufferSize )
+{
+ DWORD dwStatus = WN_NOT_CONNECTED;
+ WCHAR wchLocalName[3];
+ WCHAR wchSubstName[MAX_PATH + 1];
+ AFSNetworkProviderConnectionCB *pConnectCB = NULL;
+ DWORD dwError = 0;
+ DWORD dwBufferSize = 0;
+ DWORD dwPassedSize = *lpBufferSize;
+ DWORD dwRemainingLength = *lpBufferSize;
+ HANDLE hControlDevice = NULL;
+ DWORD dwLocalPathLength = 0;
+ DWORD dwRemainingPathLength = 0;
+ CHAR *pch;
+
+ __Enter
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName local path %s level 0x%X\n",
+ lpLocalPath ? lpLocalPath : L"(Null)",
+ dwInfoLevel);
+#endif
+
+ if ( NPIsFSDisabled())
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName AFSRDFS is disabled, returning WN_NOT_CONNECTED\n");
+#endif
+
+ try_return( dwStatus = WN_NOT_CONNECTED);
+ }
+
+ dwLocalPathLength = lstrlen( lpLocalPath);
+
+ dwRemainingPathLength = dwLocalPathLength - 2; // no drive letter
+
+ if( dwLocalPathLength == 0)
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName AFSRDFS is disabled, returning WN_BAD_LOCALNAME\n");
+#endif
+
+ try_return( dwStatus = WN_BAD_LOCALNAME);
+ }
+
+ if( lpBuffer == NULL ||
+ lpBufferSize == NULL)
+ {
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName No output buffer or size\n");
+#endif
+ try_return( dwStatus = WN_BAD_VALUE);
+ }
+
+ memset(lpBuffer, 0, dwPassedSize);
+
+ if ( !DriveSubstitution( lpLocalPath, wchSubstName, sizeof( wchSubstName)))
+ {
+ wchLocalName[0] = towupper(lpLocalPath[0]);
+ wchLocalName[1] = L':';
+ wchLocalName[2] = L'\0';
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName Requesting UNC for %s level 0x%X\n",
+ wchLocalName,
+ dwInfoLevel);
+#endif
+ }
+ else
+ {
+
+ ReadServerNameString();
+
+ if ( wchSubstName[0] != L'\\' &&
+ wchSubstName[1] == L':')
+ {
+
+ wchLocalName[0] = towupper(wchSubstName[0]);
+ wchLocalName[1] = L':';
+ wchLocalName[2] = L'\0';
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName Requesting UNC for drive substitution %s -> %s\n",
+ wchSubstName,
+ wchLocalName);
+#endif
+ }
+ else if ( _wcsnicmp( wchSubstName, wszServerNameUNC, cbServerNameUNCLength / sizeof( WCHAR)) == 0 &&
+ ( wchSubstName[cbServerNameUNCLength / sizeof( WCHAR)] == L'\\' ||
+ wchSubstName[cbServerNameUNCLength / sizeof( WCHAR)] == 0))
+ {
+ HRESULT hr;
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName drive substitution %s is AFS; Level 0x%x BufferSize 0x%x\n",
+ wchSubstName,
+ dwInfoLevel,
+ dwPassedSize);
+#endif
+
+ dwBufferSize = (wcslen( wchSubstName) + 1) * sizeof( WCHAR);
+
+ switch( dwInfoLevel)
+ {
+
+ case UNIVERSAL_NAME_INFO_LEVEL:
+ {
+
+ UNIVERSAL_NAME_INFO *pUniversalInfo = (UNIVERSAL_NAME_INFO *)lpBuffer;
+
+ *lpBufferSize = sizeof( UNIVERSAL_NAME_INFO) + dwBufferSize;
+
+ if( dwPassedSize <= sizeof( UNIVERSAL_NAME_INFO))
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName (UNIVERSAL_NAME_INFO) WN_MORE_DATA\n");
+#endif
+
+ try_return( dwStatus = WN_MORE_DATA);
+ }
+
+ dwRemainingLength -= sizeof( UNIVERSAL_NAME_INFO);
+
+ pUniversalInfo->lpUniversalName = (LPTSTR)((char *)lpBuffer + sizeof( UNIVERSAL_NAME_INFO));
+
+ memcpy( pUniversalInfo->lpUniversalName,
+ wchSubstName,
+ min( dwBufferSize, dwRemainingLength));
+
+ dwRemainingLength -= min( dwBufferSize, dwRemainingLength);
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName (UNIVERSAL_NAME_INFO_LEVEL) lpBuffer: %p Name: (%p) \"%s\"\n",
+ lpBuffer,
+ pUniversalInfo->lpUniversalName,
+ pUniversalInfo->lpUniversalName);
+#endif
+
+ if ( dwPassedSize < *lpBufferSize)
+ {
+
+ try_return( dwStatus = WN_MORE_DATA);
+ }
+
+ try_return( dwStatus = WN_SUCCESS);
+ }
+
+ case REMOTE_NAME_INFO_LEVEL:
+ {
+
+ REMOTE_NAME_INFO *pRemoteInfo = (REMOTE_NAME_INFO *)lpBuffer;
+
+ *lpBufferSize = sizeof( REMOTE_NAME_INFO) + 2 * dwBufferSize + sizeof( WCHAR);
+
+ if( dwPassedSize <= sizeof( REMOTE_NAME_INFO))
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName (REMOTE_NAME_INFO) WN_MORE_DATA\n");
+#endif
+
+ try_return( dwStatus = WN_MORE_DATA);
+ }
+
+ dwRemainingLength -= sizeof( REMOTE_NAME_INFO);
+
+ pRemoteInfo->lpUniversalName = (LPTSTR)((char *)lpBuffer + sizeof( REMOTE_NAME_INFO));
+
+ memcpy( pRemoteInfo->lpUniversalName,
+ wchSubstName,
+ min( dwRemainingLength, dwBufferSize));
+
+ dwRemainingLength -= min( dwRemainingLength, dwBufferSize);
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName (REMOTE_NAME_INFO_LEVEL) UNI lpBuffer: %p Name: (%p) \"%s\"\n",
+ lpBuffer,
+ pRemoteInfo->lpUniversalName,
+ pRemoteInfo->lpUniversalName);
+#endif
+
+ if ( dwRemainingLength > dwBufferSize + sizeof( WCHAR))
+ {
+ pRemoteInfo->lpConnectionName = (LPTSTR)((char *)pRemoteInfo->lpUniversalName + dwBufferSize);
+
+ memcpy( pRemoteInfo->lpConnectionName,
+ wchSubstName,
+ min( dwRemainingLength, dwBufferSize));
+
+ dwRemainingLength -= min( dwRemainingLength, dwBufferSize) - sizeof( WCHAR);
+
+ SeparateRemainingPath( pRemoteInfo->lpConnectionName,
+ &pRemoteInfo->lpRemainingPath);
+ }
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName (REMOTE_NAME_INFO_LEVEL) CONN lpBuffer: %p Name: (%p) \"%s\"\n",
+ lpBuffer,
+ pRemoteInfo->lpConnectionName,
+ pRemoteInfo->lpConnectionName ? pRemoteInfo->lpConnectionName : L"(null)");
+
+ AFSDbgPrint( L"NPGetUniversalName (REMOTE_NAME_INFO_LEVEL) REMAIN lpBuffer: %p Name: (%p) \"%s\"\n",
+ lpBuffer,
+ pRemoteInfo->lpRemainingPath,
+ pRemoteInfo->lpRemainingPath ? pRemoteInfo->lpRemainingPath : L"(null)");
+#endif
+
+ if ( dwPassedSize < *lpBufferSize)
+ {
+
+ try_return( dwStatus = WN_MORE_DATA);
+ }
+
+ try_return( dwStatus = WN_SUCCESS);
+ }
+
+ default:
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName (UNKNOWN: 0x%X) WN_BAD_VALUE\n",
+ dwInfoLevel);
+#endif
+ try_return( dwStatus = WN_BAD_VALUE);
+ }
+ }
+ else
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName drive substitution %s is not AFS\n",
+ wchSubstName);
+#endif
+ try_return( dwStatus = WN_NOT_CONNECTED);
+ }
+ }
+
+ dwBufferSize = 0x1000;
+
+ pConnectCB = (AFSNetworkProviderConnectionCB *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufferSize);
+
+ if( pConnectCB == NULL)
+ {
+ try_return( dwStatus = WN_OUT_OF_MEMORY);
+ }
+
+ pConnectCB->LocalName = towupper(wchLocalName[0]);
+
+ pConnectCB->RemoteNameLength = 0;
+
+ pConnectCB->Version = AFS_NETWORKPROVIDER_INTERFACE_VERSION_1;
+
+ pConnectCB->AuthenticationId = AFSRetrieveAuthId();
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName Retrieved authentication id %08lX-%08lX\n",
+ pConnectCB->AuthenticationId.HighPart,
+ pConnectCB->AuthenticationId.LowPart);
+#endif
+
+ hControlDevice = OpenRedirector();
+
+ if( hControlDevice == NULL)
+ {
+
+ try_return( dwStatus = WN_NET_ERROR);
+ }
+
+ dwError = DeviceIoControl( hControlDevice,
+ IOCTL_AFS_GET_CONNECTION,
+ pConnectCB,
+ dwBufferSize,
+ pConnectCB,
+ dwBufferSize,
+ &dwBufferSize,
+ NULL);
+
+ if( !dwError)
+ {
+#ifdef AFS_DEBUG_TRACE
+ DWORD gle = GetLastError();
+
+ AFSDbgPrint( L"NPGetUniversalName Failed to get connection from file system for local %s gle 0x%x\n",
+ wchLocalName, gle);
+#endif
+ try_return( dwStatus = WN_NOT_CONNECTED);
+ }
+
+ switch( dwInfoLevel)
+ {
+
+ case UNIVERSAL_NAME_INFO_LEVEL:
+ {
+
+ UNIVERSAL_NAME_INFO *pUniversalInfo = (UNIVERSAL_NAME_INFO *)lpBuffer;
+
+ *lpBufferSize = sizeof( UNIVERSAL_NAME_INFO) + dwBufferSize + sizeof( WCHAR);
+
+ *lpBufferSize += dwRemainingPathLength * sizeof( WCHAR);
+
+ if( dwPassedSize <= sizeof( UNIVERSAL_NAME_INFO))
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName (UNIVERSAL_NAME_INFO) WN_MORE_DATA\n");
+#endif
+
+ try_return( dwStatus = WN_MORE_DATA);
+ }
+
+ dwRemainingLength -= sizeof( UNIVERSAL_NAME_INFO);
+
+ pUniversalInfo->lpUniversalName = (LPTSTR)((char *)lpBuffer + sizeof( UNIVERSAL_NAME_INFO));
+
+ pch = (char *)pUniversalInfo->lpUniversalName;
+
+ memcpy( pch,
+ pConnectCB,
+ min( dwBufferSize, dwRemainingLength));
+
+ pch += min( dwBufferSize, dwRemainingLength);
+
+ dwRemainingLength -= min( dwBufferSize + sizeof(WCHAR), dwRemainingLength);
+
+ memcpy( pch,
+ &lpLocalPath[2],
+ min(dwRemainingPathLength * sizeof( WCHAR), dwRemainingLength));
+
+ pch += min(dwRemainingPathLength * sizeof( WCHAR), dwRemainingLength);
+
+ dwRemainingLength -= min(dwRemainingPathLength * sizeof( WCHAR), dwRemainingLength);
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName (UNIVERSAL_NAME_INFO_LEVEL) lpBuffer: %p Name: (%p) \"%s\"\n",
+ lpBuffer,
+ pUniversalInfo->lpUniversalName,
+ pUniversalInfo->lpUniversalName);
+#endif
+
+ if ( dwPassedSize < *lpBufferSize)
+ {
+
+ try_return( dwStatus = WN_MORE_DATA);
+ }
+
+ try_return( dwStatus = WN_SUCCESS);
+ }
+
+ case REMOTE_NAME_INFO_LEVEL:
+ {
+
+ REMOTE_NAME_INFO *pRemoteInfo = (REMOTE_NAME_INFO *)lpBuffer;
+
+ *lpBufferSize = sizeof( REMOTE_NAME_INFO) + (2 * dwBufferSize + sizeof( WCHAR)) + 2 * sizeof( WCHAR);
+
+ *lpBufferSize += 2 * dwRemainingPathLength * sizeof( WCHAR);
+
+ if( dwPassedSize <= sizeof( REMOTE_NAME_INFO))
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName (REMOTE_NAME_INFO) WN_MORE_DATA\n");
+#endif
+
+ try_return( dwStatus = WN_MORE_DATA);
+ }
+
+ dwRemainingLength -= sizeof( REMOTE_NAME_INFO);
+
+ pRemoteInfo->lpUniversalName = (LPTSTR)((char *)lpBuffer + sizeof( REMOTE_NAME_INFO));
+
+ pch = (char *)pRemoteInfo->lpUniversalName;
+
+ memcpy( pch,
+ pConnectCB,
+ min( dwBufferSize, dwRemainingLength));
+
+ pch += min( dwBufferSize, dwRemainingLength);
+
+ dwRemainingLength -= min( dwBufferSize + sizeof( WCHAR), dwRemainingLength);
+
+ memcpy( pch,
+ &lpLocalPath[2],
+ min(dwRemainingPathLength * sizeof( WCHAR), dwRemainingLength));
+
+ pch += min((dwRemainingPathLength + 1) * sizeof( WCHAR), dwRemainingLength);
+
+ dwRemainingLength -= min((dwRemainingPathLength + 1) * sizeof( WCHAR), dwRemainingLength);
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName (REMOTE_NAME_INFO_LEVEL) UNI lpBuffer: %p Name: (%p) \"%s\"\n",
+ lpBuffer,
+ pRemoteInfo->lpUniversalName,
+ pRemoteInfo->lpUniversalName);
+#endif
+
+ if ( dwRemainingLength > dwBufferSize + sizeof( WCHAR))
+ {
+ pRemoteInfo->lpConnectionName = (LPWSTR)pch;
+
+ memcpy( pch,
+ pConnectCB,
+ min( dwBufferSize, dwRemainingLength));
+
+ pch += min( dwBufferSize + sizeof( WCHAR), dwRemainingLength);
+
+ dwRemainingLength -= min( dwBufferSize + sizeof( WCHAR), dwRemainingLength);
+ }
+
+
+ if ( dwRemainingLength > dwRemainingPathLength + sizeof( WCHAR))
+ {
+ pRemoteInfo->lpRemainingPath = (LPWSTR)pch;
+
+ memcpy( pch,
+ &lpLocalPath[2],
+ min((dwRemainingPathLength + 1) * sizeof( WCHAR), dwRemainingLength));
+
+ pch += min((dwRemainingPathLength + 1) * sizeof( WCHAR), dwRemainingLength);
+
+ dwRemainingLength -= min((dwLocalPathLength + 1) * sizeof( WCHAR), dwRemainingLength);
+ }
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName (REMOTE_NAME_INFO_LEVEL) CONN lpBuffer: %p Name: (%p) \"%s\"\n",
+ lpBuffer,
+ pRemoteInfo->lpConnectionName,
+ pRemoteInfo->lpConnectionName ? pRemoteInfo->lpConnectionName : L"(null)");
+
+ AFSDbgPrint( L"NPGetUniversalName (REMOTE_NAME_INFO_LEVEL) REMAIN lpBuffer: %p Name: (%p) \"%s\"\n",
+ lpBuffer,
+ pRemoteInfo->lpRemainingPath,
+ pRemoteInfo->lpRemainingPath ? pRemoteInfo->lpRemainingPath : L"(null)");
+#endif
+
+ if ( dwPassedSize < *lpBufferSize)
+ {
+
+ try_return( dwStatus = WN_MORE_DATA);
+ }
+
+ try_return( dwStatus = WN_SUCCESS);
+ }
+
+ default:
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName (UNKNOWN: 0x%X) WN_BAD_VALUE\n",
+ dwInfoLevel);
+#endif
+ try_return( dwStatus = WN_BAD_VALUE);
+ }
+
+try_exit:
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPGetUniversalName BufferSize 0x%X\n",
+ *lpBufferSize);
+#endif
+ if ( hControlDevice != NULL)
+ {
+
+ CloseHandle( hControlDevice);
+ }
+
+ if( pConnectCB != NULL)
+ {
+
+ HeapFree( GetProcessHeap( ), 0, (PVOID) pConnectCB);
+ }
+ }
+
+ return dwStatus;
+}
+
+
+static LPCWSTR
+GetFormatFlags( DWORD dwFlags)
+{
+ static WCHAR Buffer[128] = L"";
+
+ //
+ // WNFMT_MULTILINE 0x01
+ // WNFMT_ABBREVIATED 0x02
+ // WNFMT_INENUM 0x10
+ // WNFMT_CONNECTION 0x20
+ //
+
+ Buffer[0] = L'\0';
+
+ if ( dwFlags & WNFMT_MULTILINE )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"MULTILINE|");
+ }
+
+ if ( dwFlags & WNFMT_INENUM )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"ABBREVIATED|");
+ }
+
+ if ( dwFlags & WNFMT_INENUM )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"INENUM|");
+ }
+
+ if ( dwFlags & WNFMT_CONNECTION )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"CONNECTION|");
+ }
+
+ if ( dwFlags & ~(WNFMT_MULTILINE|WNFMT_ABBREVIATED|WNFMT_INENUM|WNFMT_CONNECTION) )
+ {
+ StringCbCat( Buffer, sizeof(Buffer), L"UNKNOWN|");
+ }
+
+ Buffer[lstrlen(Buffer)-1] = L'\0';
+
+ return Buffer;
+}
+
+DWORD
+NPFormatNetworkName( LPTSTR lpRemoteName,
+ LPTSTR lpFormattedName,
+ LPDWORD lpnLength,
+ DWORD dwFlags,
+ DWORD dwAveCharPerLine)
+{
+
+ DWORD dwLen = 0, dwCurrentLen = 0;
+ LPTSTR pCurrentName = lpRemoteName;
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPFormatNetworkName Remote %s Flags %s (0x%x) CharsPerLine %u\n",
+ lpRemoteName,
+ dwFlags,
+ GetFormatFlags( dwFlags),
+ dwAveCharPerLine);
+#endif
+
+
+ //
+ // Walk back in the name until we hit a \
+ //
+
+ dwLen = wcslen( lpRemoteName);
+
+ pCurrentName += (dwLen - 1);
+
+ if ( pCurrentName[ 0] != L'\\')
+ {
+
+ while( dwLen > 0)
+ {
+
+ if( pCurrentName[ 0] == L'\\')
+ {
+
+ pCurrentName++;
+
+ break;
+ }
+
+ pCurrentName--;
+
+ dwLen--;
+
+ dwCurrentLen++;
+ }
+ }
+
+ if( *lpnLength < dwCurrentLen * sizeof( WCHAR))
+ {
+
+ *lpnLength = dwCurrentLen * sizeof( WCHAR);
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPFormatNetworkName remote name %s WN_MORE_DATA\n",
+ lpRemoteName);
+#endif
+
+ return WN_MORE_DATA;
+ }
+
+ StringCbCopy( lpFormattedName,
+ *lpnLength,
+ pCurrentName);
+
+ *lpnLength = dwCurrentLen * sizeof( WCHAR);
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPFormatNetworkName remote name %s as %s\n",
+ lpRemoteName,
+ lpFormattedName);
+#endif
+
+ return WN_SUCCESS;
+}
+
+/************************************************************
+/ Unsupported entry points
+/************************************************************/
+
+//
+// AuthGroup processing is implemented in src/WINNT/afsd/afslogon.c
+//
+DWORD APIENTRY
+NPLogonNotify(
+ PLUID lpLogonId,
+ LPCWSTR lpAuthentInfoType,
+ LPVOID lpAuthentInfo,
+ LPCWSTR lpPreviousAuthentInfoType,
+ LPVOID lpPreviousAuthentInfo,
+ LPWSTR lpStationName,
+ LPVOID StationHandle,
+ LPWSTR *lpLogonScript)
+{
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPLogonNotify, returning WN_NOT_SUPPORTED\n");
+#endif
+
+ return WN_NOT_SUPPORTED;
+}
+
+DWORD APIENTRY
+NPPasswordChangeNotify (
+ LPCWSTR lpAuthentInfoType,
+ LPVOID lpAuthentInfo,
+ LPCWSTR lpPreviousAuthentInfoType,
+ LPVOID lpPreviousAuthentInfo,
+ LPWSTR lpStationName,
+ LPVOID StationHandle,
+ DWORD dwChangeInfo )
+{
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"NPPasswordChangeNotify, returning WN_NOT_SUPPORTED\n");
+#endif
+
+ SetLastError( WN_NOT_SUPPORTED );
+
+ return WN_NOT_SUPPORTED;
+}
+
+DWORD APIENTRY
+NPGetUser( LPTSTR lpName,
+ LPTSTR lpUserName,
+ LPDWORD lpBufferSize)
+{
+
+ DWORD rc = WN_NOT_SUPPORTED;
+
+ AFSDbgPrint( L"NPGetUser Entry Name %s\n", lpName);
+
+ return rc;
+}
+
+
+DWORD
+APIENTRY
+NPGetReconnectFlags( LPWSTR lpRemoteName,
+ unsigned char *Parameter2)
+{
+
+ DWORD dwStatus = WN_NOT_SUPPORTED;
+
+ AFSDbgPrint( L"NPGetReconnectFlags RemoteName %s\n",
+ lpRemoteName);
+
+ return dwStatus;
+}
+
+
+DWORD
+APIENTRY
+I_SystemFocusDialog( VOID)
+{
+
+ DWORD dwStatus = WN_NOT_SUPPORTED;
+
+ AFSDbgPrint( L"I_SystemFocusDialog\n");
+
+ return dwStatus;
+}
+
+/************************************************************
+/ END Unsupported entry points
+/************************************************************/
+
+
+HANDLE
+OpenRedirector()
+{
+
+ HANDLE hControlDevice = NULL;
+ WCHAR wchError[ 256];
+
+ hControlDevice = CreateFile( AFS_SYMLINK_W,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL );
+
+ if( hControlDevice == INVALID_HANDLE_VALUE)
+ {
+
+ hControlDevice = NULL;
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"Failed to open control device error: %d\n",
+ GetLastError());
+#endif
+ }
+#if 0
+ //
+ // only do this if you want network shares to fail to mount
+ // when the file system is not yet ready
+ //
+ else {
+
+ AFSDriverStatusRespCB respCB;
+ DWORD dwBytes;
+
+ memset( &respCB, '\0', sizeof( AFSDriverStatusRespCB));
+
+ if ( !DeviceIoControl( hControlDevice,
+ IOCTL_AFS_STATUS_REQUEST,
+ NULL,
+ 0,
+ (void *)&respCB,
+ sizeof( AFSDriverStatusRespCB),
+ &dwBytes,
+ NULL) ||
+ dwBytes != sizeof(AFSDriverStatusRespCB) ||
+ respCB.Status != AFS_DRIVER_STATUS_READY )
+ {
+
+ CloseHandle( hControlDevice);
+
+ hControlDevice = NULL;
+ }
+ }
+#endif
+
+ return hControlDevice;
+}
+
+LARGE_INTEGER
+AFSRetrieveAuthId()
+{
+
+ LARGE_INTEGER liAuthId = {0,0};
+ HANDLE hToken = NULL;
+ TOKEN_STATISTICS stTokenInfo;
+ DWORD dwCopyBytes = 0;
+
+ if ( !OpenThreadToken( GetCurrentThread(),
+ TOKEN_QUERY,
+ FALSE, // Impersonation
+ &hToken))
+ {
+ if( !OpenProcessToken( GetCurrentProcess(),
+ TOKEN_QUERY,
+ &hToken))
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"AFSRetrieveAuthId Failed to retrieve Thread and Process tokens 0x%X\n",
+ GetLastError());
+#endif
+ }
+ else
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"AFSRetrieveAuthId Retrieved Process Token\n");
+#endif
+ }
+ }
+ else
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"AFSRetrieveAuthId Retrieved Thread Token\n");
+#endif
+ }
+
+ if ( hToken != NULL)
+ {
+
+ if( !GetTokenInformation( hToken,
+ TokenStatistics,
+ &stTokenInfo,
+ sizeof( TOKEN_STATISTICS),
+ &dwCopyBytes))
+ {
+
+#ifdef AFS_DEBUG_TRACE
+ AFSDbgPrint( L"AFSRetrieveAuthId Failed to retrieve token information 0x%X\n",
+ GetLastError());
+#endif
+ }
+ else
+ {
+
+ liAuthId.HighPart = stTokenInfo.AuthenticationId.HighPart;
+ liAuthId.LowPart = stTokenInfo.AuthenticationId.LowPart;
+ }
+
+ CloseHandle( hToken);
+ }
+
+ return liAuthId;
+}
+
+static BOOL
+Debug(void)
+{
+ static int init = 0;
+ static BOOL debug = 0;
+
+ if ( !init ) {
+ HKEY hk;
+
+ if (RegOpenKey (HKEY_LOCAL_MACHINE,
+ TEXT("SYSTEM\\CurrentControlSet\\Services\\AFSRedirector\\NetworkProvider"), &hk) == 0)
+ {
+ DWORD dwSize = sizeof(BOOL);
+ DWORD dwType = REG_DWORD;
+ RegQueryValueEx (hk, TEXT("Debug"), NULL, &dwType, (PBYTE)&debug, &dwSize);
+ RegCloseKey (hk);
+ }
+ init = 1;
+ }
+
+ return debug;
+}
+
+ULONG
+_cdecl
+AFSDbgPrint(
+ PWCHAR Format,
+ ...
+ )
+{
+ HRESULT rc = S_OK;
+ WCHAR wszbuffer[512];
+ va_list marker;
+
+ if ( !Debug() )
+ return 0;
+
+ va_start( marker, Format );
+ {
+ StringCbPrintf( wszbuffer, sizeof(wszbuffer), L"[%d-%08X] ",
+#ifdef AMD64
+ 64,
+#else
+ 32,
+#endif
+ GetCurrentThreadId());
+
+ rc = StringCbVPrintfW( &wszbuffer[ 14], sizeof(wszbuffer) - 14, Format, marker);
+
+ if (SUCCEEDED(rc))
+ OutputDebugString( wszbuffer );
+ else
+ OutputDebugString(L"AFSDbgPrint Failed to create string\n");
+ }
+ return SUCCEEDED(rc) ? 1 : 0;
+}
diff --git a/src/WINNT/afsrdr/npdll/AFS_Npdll.h b/src/WINNT/afsrdr/npdll/AFS_Npdll.h
new file mode 100644
index 0000000000..4e4cbb5f1b
--- /dev/null
+++ b/src/WINNT/afsrdr/npdll/AFS_Npdll.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2008 Kernel Drivers, LLC.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice,
+ * this list of conditions and the following disclaimer in the
+ * documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of Kernel Drivers, LLC nor the names of its
+ * contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission from Kernel Drivers, LLC.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+void ReadProviderNameString( void);
diff --git a/src/WINNT/afsrdr/npdll/AFS_Npdll.rc b/src/WINNT/afsrdr/npdll/AFS_Npdll.rc
new file mode 100644
index 0000000000..77a014436c
--- /dev/null
+++ b/src/WINNT/afsrdr/npdll/AFS_Npdll.rc
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
+ * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice,
+ * this list of conditions and the following disclaimer in the
+ * documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
+ * nor the names of their contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission from Kernel Drivers, LLC and Your File System, Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Define VERSIONINFO resource */
+
+#define AFS_VERINFO_FILE_DESCRIPTION "AFS Redirector Network Provider"
+#define AFS_VERINFO_NAME "AFSRDFSProvider"
+#define AFS_VERINFO_FILENAME "AFSRDFSProvider.dll"
+
+#include "..\AFS_component_version_number.h"
+#include "..\..\..\config\NTVersioninfo.rc"
diff --git a/src/WINNT/afsrdr/npdll/AFS_NpdllMain.C b/src/WINNT/afsrdr/npdll/AFS_NpdllMain.C
new file mode 100644
index 0000000000..ef1d6b912c
--- /dev/null
+++ b/src/WINNT/afsrdr/npdll/AFS_NpdllMain.C
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
+ * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice,
+ * this list of conditions and the following disclaimer in the
+ * documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
+ * nor the names of their contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission from Kernel Drivers, LLC and Your File System, Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include
+#define _DECL_DLLMAIN
+#include
+#include "AFS_Npdll.h"
+
+// NOTE:
+//
+// Function: DllMain
+//
+// Return: TRUE => Success
+// FALSE => Failure
+
+BOOL
+WINAPI
+DllMain( HINSTANCE hDLLInst,
+ DWORD fdwReason,
+ LPVOID lpvReserved)
+{
+ BOOL bStatus = TRUE;
+ WORD wVersionRequested;
+
+ switch( fdwReason)
+ {
+
+ case DLL_PROCESS_ATTACH:
+ ReadProviderNameString();
+ break;
+
+ case DLL_PROCESS_DETACH:
+ break;
+
+ case DLL_THREAD_ATTACH:
+ break;
+
+ case DLL_THREAD_DETACH:
+ break;
+
+ default:
+ break;
+ }
+
+ return( bStatus);
+}
diff --git a/src/WINNT/afsrdr/npdll/SOURCES b/src/WINNT/afsrdr/npdll/SOURCES
new file mode 100644
index 0000000000..0baa11051a
--- /dev/null
+++ b/src/WINNT/afsrdr/npdll/SOURCES
@@ -0,0 +1,31 @@
+
+TARGETNAME=AFSRDFSProvider
+TARGETPATH=..\build
+TARGETTYPE=DYNLINK
+
+TARGETLIBS=$(DDK_LIB_PATH)\user32.lib \
+ $(DDK_LIB_PATH)\kernel32.lib \
+ $(DDK_LIB_PATH)\Advapi32.lib
+
+
+UNICODE=1
+NET_C_DEFINES=-DUNICODE
+
+DLLBASE=0x1010000
+
+USE_NTDLL=0
+
+!IF $(FREEBUILD)
+C_DEFINES=$(C_DEFINES)
+!endif
+
+INCLUDES=$(IFSKIT_INC_PATH);..\Common;
+
+SOURCES= AFS_NpdllMain.c \
+ AFS_Npdll.c \
+ AFS_Npdll.rc
+
+UMTYPE=console
+OPTIONAL_NTTEST=
+
+DLLDEF=AFS_Npdll.def
diff --git a/src/WINNT/afsrdr/npdll/tests/enumresources.c b/src/WINNT/afsrdr/npdll/tests/enumresources.c
new file mode 100644
index 0000000000..06036e8070
--- /dev/null
+++ b/src/WINNT/afsrdr/npdll/tests/enumresources.c
@@ -0,0 +1,322 @@
+/*
+ * This test code was obtained from
+ * http://msdn.microsoft.com/en-us/library/aa385341(VS.85).aspx
+ *
+ * No license specified.
+ */
+
+#pragma comment(lib, "mpr.lib")
+
+#ifndef UNICODE
+#define UNICODE
+#endif
+
+#include
+#include
+#include
+
+BOOL WINAPI EnumerateFunc(DWORD dwScope, LPNETRESOURCE lpnr);
+void DisplayStruct(int i, LPNETRESOURCE lpnrLocal);
+BOOL WINAPI NetErrorHandler(HWND hwnd, DWORD dwErrorCode, LPSTR lpszFunction);
+
+int main()
+{
+
+ LPNETRESOURCE lpnr = NULL;
+
+ printf("Connected Resources\n");
+ printf("-------------------\n");
+ if (EnumerateFunc(RESOURCE_CONNECTED, lpnr) == FALSE) {
+ printf("Call to EnumerateFunc(CONNECTED) failed\n");
+ return 1;
+ }
+
+ printf("\n");
+ printf("Context Resources\n");
+ printf("-----------------\n");
+ if (EnumerateFunc(RESOURCE_CONTEXT, lpnr) == FALSE) {
+ printf("Call to EnumerateFunc(CONTEXT) failed\n");
+ return 1;
+ }
+
+ printf("\n");
+ printf("Global Resources\n");
+ printf("----------------\n");
+ if (EnumerateFunc(RESOURCE_GLOBALNET, lpnr) == FALSE) {
+ printf("Call to EnumerateFunc(GLOBALNET) failed\n");
+ return 1;
+ }
+
+ printf("\n");
+ printf("Remembered Resources\n");
+ printf("--------------------\n");
+ if (EnumerateFunc(RESOURCE_REMEMBERED, lpnr) == FALSE) {
+ printf("Call to EnumerateFunc(REMEMBERED) failed\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+BOOL WINAPI EnumerateFunc(DWORD dwScope, LPNETRESOURCE lpnr)
+{
+ DWORD dwResult, dwResultEnum;
+ HANDLE hEnum;
+ DWORD cbBuffer = 16384; // 16K is a good size
+ DWORD cEntries = -1; // enumerate all possible entries
+ LPNETRESOURCE lpnrLocal; // pointer to enumerated structures
+ DWORD i;
+ //
+ // Call the WNetOpenEnum function to begin the enumeration.
+ //
+ dwResult = WNetOpenEnum(dwScope, // all network resources
+ RESOURCETYPE_DISK, // all resources
+ RESOURCEUSAGE_ALL, // enumerate all resources
+ lpnr, // NULL first time the function is called
+ &hEnum); // handle to the resource
+
+ if (dwResult != NO_ERROR) {
+ printf("WnetOpenEnum failed with error %d\n", dwResult);
+ return FALSE;
+ }
+ //
+ // Call the GlobalAlloc function to allocate resources.
+ //
+ lpnrLocal = (LPNETRESOURCE) GlobalAlloc(GPTR, cbBuffer);
+ if (lpnrLocal == NULL) {
+ printf("WnetOpenEnum failed with error %d\n", dwResult);
+ return FALSE;
+ }
+
+ do {
+ //
+ // Initialize the buffer.
+ //
+ ZeroMemory(lpnrLocal, cbBuffer);
+ //
+ // Call the WNetEnumResource function to continue
+ // the enumeration.
+ //
+ cEntries = -1;
+ dwResultEnum = WNetEnumResource(hEnum, // resource handle
+ &cEntries, // defined locally as -1
+ lpnrLocal, // LPNETRESOURCE
+ &cbBuffer); // buffer size
+ //
+ // If the call succeeds, loop through the structures.
+ //
+ if (dwResultEnum == NO_ERROR) {
+ for (i = 0; i < cEntries; i++) {
+ // Call an application-defined function to
+ // display the contents of the NETRESOURCE structures.
+ //
+ DisplayStruct(i, &lpnrLocal[i]);
+
+ // If the NETRESOURCE structure represents a container resource,
+ // call the EnumerateFunc function recursively.
+
+ if (dwScope == RESOURCE_GLOBALNET &&
+ RESOURCEUSAGE_CONTAINER == (lpnrLocal[i].dwUsage
+ & RESOURCEUSAGE_CONTAINER))
+ if (!EnumerateFunc(dwScope, &lpnrLocal[i]))
+ printf("EnumerateFunc returned FALSE\n");
+ }
+ }
+ // Process errors.
+ //
+ else if (dwResultEnum != ERROR_NO_MORE_ITEMS) {
+ printf("WNetEnumResource failed with error %d\n", dwResultEnum);
+ break;
+ }
+ }
+ //
+ // End do.
+ //
+ while (dwResultEnum != ERROR_NO_MORE_ITEMS);
+ //
+ // Call the GlobalFree function to free the memory.
+ //
+ GlobalFree((HGLOBAL) lpnrLocal);
+ //
+ // Call WNetCloseEnum to end the enumeration.
+ //
+ dwResult = WNetCloseEnum(hEnum);
+
+ if (dwResult != NO_ERROR) {
+ //
+ // Process errors.
+ //
+ printf("WNetCloseEnum failed with error %d\n\n", dwResult);
+// NetErrorHandler(hwnd, dwResult, (LPSTR)"WNetCloseEnum");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void DisplayStruct(int i, LPNETRESOURCE lpnrLocal)
+{
+ printf("NETRESOURCE[%d] Scope: ", i);
+ switch (lpnrLocal->dwScope) {
+ case (RESOURCE_CONNECTED):
+ printf("connected\n");
+ break;
+ case (RESOURCE_GLOBALNET):
+ printf("all resources\n");
+ break;
+ case (RESOURCE_REMEMBERED):
+ printf("remembered\n");
+ break;
+ case RESOURCE_RECENT:
+ printf("recent\n");
+ break;
+ case RESOURCE_CONTEXT:
+ printf("context\n");
+ break;
+ default:
+ printf("unknown scope %d\n", lpnrLocal->dwScope);
+ break;
+ }
+
+ printf("NETRESOURCE[%d] Type: ", i);
+ switch (lpnrLocal->dwType) {
+ case (RESOURCETYPE_ANY):
+ printf("any\n");
+ break;
+ case (RESOURCETYPE_DISK):
+ printf("disk\n");
+ break;
+ case (RESOURCETYPE_PRINT):
+ printf("print\n");
+ break;
+ case RESOURCETYPE_RESERVED:
+ printf("reserved\n");
+ break;
+ default:
+ printf("unknown type %d\n", lpnrLocal->dwType);
+ break;
+ }
+
+ printf("NETRESOURCE[%d] DisplayType: ", i);
+ switch (lpnrLocal->dwDisplayType) {
+ case (RESOURCEDISPLAYTYPE_GENERIC):
+ printf("generic\n");
+ break;
+ case (RESOURCEDISPLAYTYPE_DOMAIN):
+ printf("domain\n");
+ break;
+ case (RESOURCEDISPLAYTYPE_SERVER):
+ printf("server\n");
+ break;
+ case (RESOURCEDISPLAYTYPE_SHARE):
+ printf("share\n");
+ break;
+ case (RESOURCEDISPLAYTYPE_FILE):
+ printf("file\n");
+ break;
+ case (RESOURCEDISPLAYTYPE_GROUP):
+ printf("group\n");
+ break;
+ case (RESOURCEDISPLAYTYPE_NETWORK):
+ printf("network\n");
+ break;
+ case RESOURCEDISPLAYTYPE_ROOT:
+ printf("root\n");
+ break;
+ case RESOURCEDISPLAYTYPE_SHAREADMIN:
+ printf("share-admin\n");
+ break;
+ case RESOURCEDISPLAYTYPE_DIRECTORY:
+ printf("directory\n");
+ break;
+ case RESOURCEDISPLAYTYPE_TREE:
+ printf("tree\n");
+ break;
+ case RESOURCEDISPLAYTYPE_NDSCONTAINER:
+ printf("nds-container\n");
+ break;
+ default:
+ printf("unknown display type %d\n", lpnrLocal->dwDisplayType);
+ break;
+ }
+
+ printf("NETRESOURCE[%d] Usage: 0x%x = ", i, lpnrLocal->dwUsage);
+ if (lpnrLocal->dwUsage & RESOURCEUSAGE_CONNECTABLE)
+ printf("connectable ");
+ if (lpnrLocal->dwUsage & RESOURCEUSAGE_CONTAINER)
+ printf("container ");
+ if (lpnrLocal->dwUsage & RESOURCEUSAGE_NOLOCALDEVICE)
+ printf("no-local ");
+ if (lpnrLocal->dwUsage & RESOURCEUSAGE_SIBLING)
+ printf("sibling ");
+ if (lpnrLocal->dwUsage & RESOURCEUSAGE_ATTACHED)
+ printf("attached ");
+ if (lpnrLocal->dwUsage & RESOURCEUSAGE_RESERVED)
+ printf("reserved ");
+ printf("\n");
+
+ printf("NETRESOURCE[%d] Localname: %S\n", i, lpnrLocal->lpLocalName);
+ printf("NETRESOURCE[%d] Remotename: %S\n", i, lpnrLocal->lpRemoteName);
+ printf("NETRESOURCE[%d] Comment: %S\n", i, lpnrLocal->lpComment);
+ printf("NETRESOURCE[%d] Provider: %S\n", i, lpnrLocal->lpProvider);
+ printf("\n");
+}
+
+
+/*
+BOOL WINAPI NetErrorHandler(HWND hwnd,
+ DWORD dwErrorCode,
+ LPSTR lpszFunction)
+{
+ DWORD dwWNetResult, dwLastError;
+ CHAR szError[256];
+ CHAR szCaption[256];
+ CHAR szDescription[256];
+ CHAR szProvider[256];
+
+ // The following code performs standard error-handling.
+
+ if (dwErrorCode != ERROR_EXTENDED_ERROR)
+ {
+ sprintf_s((LPSTR) szError, sizeof(szError), "%s failed; \nResult is %ld",
+ lpszFunction, dwErrorCode);
+ sprintf_s((LPSTR) szCaption, sizeof(szCaption), "%s error", lpszFunction);
+ MessageBox(hwnd, (LPSTR) szError, (LPSTR) szCaption, MB_OK);
+ return TRUE;
+ }
+
+ // The following code performs error-handling when the
+ // ERROR_EXTENDED_ERROR return value indicates that the
+ // WNetGetLastError function can retrieve additional information.
+
+ else
+ {
+ dwWNetResult = WNetGetLastError(&dwLastError, // error code
+ (LPSTR) szDescription, // buffer for error description
+ sizeof(szDescription), // size of error buffer
+ (LPSTR) szProvider, // buffer for provider name
+ sizeof(szProvider)); // size of name buffer
+
+ //
+ // Process errors.
+ //
+ if(dwWNetResult != NO_ERROR) {
+ sprintf_s((LPSTR) szError, sizeof(szError),
+ "WNetGetLastError failed; error %ld", dwWNetResult);
+ MessageBox(hwnd, (LPSTR) szError,
+ "WNetGetLastError", MB_OK);
+ return FALSE;
+ }
+
+ //
+ // Otherwise, print the additional error information.
+ //
+ sprintf_((LPSTR) szError, sizeof(szError),
+ "%s failed with code %ld;\n%s",
+ (LPSTR) szProvider, dwLastError, (LPSTR) szDescription);
+ sprintf_s((LPSTR) szCaption, sizeof(szCaption), "%s error", lpszFunction);
+ MessageBox(hwnd, (LPSTR) szError, (LPSTR) szCaption, MB_OK);
+ return TRUE;
+ }
+}
+*/