2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSNetworkProviderSupport.cpp
39 #include "AFSCommon.h"
42 AFSAddConnectionEx( IN UNICODE_STRING *RemoteName,
47 NTSTATUS ntStatus = STATUS_SUCCESS;
48 AFSProviderConnectionCB *pConnection = NULL, *pLastConnection = NULL, *pServerConnection = NULL;
49 UNICODE_STRING uniRemoteName;
50 AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
55 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
56 AFS_TRACE_LEVEL_VERBOSE,
57 "AFSAddConnectionEx Acquiring AFSProviderListLock lock %08lX EXCL %08lX\n",
58 &pRDRDevExt->Specific.RDR.ProviderListLock,
59 PsGetCurrentThread());
61 AFSAcquireExcl( &pRDRDevExt->Specific.RDR.ProviderListLock,
65 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
66 AFS_TRACE_LEVEL_VERBOSE,
67 "AFSAddConnectionEx remote name %wZ display type %08lX flags %08lX\n",
73 // If this is a server, start in the enum list, otherwise
74 // locate the server node
77 if( DisplayType == RESOURCEDISPLAYTYPE_SERVER)
80 pConnection = pRDRDevExt->Specific.RDR.ProviderEnumerationList;
85 pServerConnection = pRDRDevExt->Specific.RDR.ProviderEnumerationList; // For now we have only one server ...
87 if( pServerConnection == NULL)
90 try_return( ntStatus);
93 pConnection = pServerConnection->EnumerationList;
97 // Look for the connection
100 uniRemoteName.Length = RemoteName->Length;
101 uniRemoteName.MaximumLength = RemoteName->Length;
103 uniRemoteName.Buffer = RemoteName->Buffer;
105 while( pConnection != NULL)
108 if( RtlCompareUnicodeString( &uniRemoteName,
109 &pConnection->RemoteName,
116 pConnection = pConnection->fLink;
119 if( pConnection != NULL)
122 try_return( ntStatus);
126 // Strip off any trailing slashes
129 if( uniRemoteName.Buffer[ (uniRemoteName.Length/sizeof( WCHAR)) - 1] == L'\\')
132 uniRemoteName.Buffer[ (uniRemoteName.Length/sizeof( WCHAR)) - 1] = L'\0';
134 uniRemoteName.Length -= sizeof( WCHAR);
137 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
138 AFS_TRACE_LEVEL_VERBOSE,
139 "AFSAddConnectionEx Inserting remote name %wZ\n", &uniRemoteName);
142 // Allocate a new node and add it to our list
145 pConnection = (AFSProviderConnectionCB *)AFSExAllocatePoolWithTag( PagedPool,
146 sizeof( AFSProviderConnectionCB) +
147 uniRemoteName.Length,
150 if( pConnection == NULL)
153 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
156 RtlZeroMemory( pConnection,
157 sizeof( AFSProviderConnectionCB) + uniRemoteName.Length);
159 pConnection->LocalName = L'\0';
161 pConnection->RemoteName.Length = uniRemoteName.Length;
162 pConnection->RemoteName.MaximumLength = pConnection->RemoteName.Length;
164 pConnection->RemoteName.Buffer = (WCHAR *)((char *)pConnection + sizeof( AFSProviderConnectionCB));
166 RtlCopyMemory( pConnection->RemoteName.Buffer,
167 uniRemoteName.Buffer,
168 pConnection->RemoteName.Length);
171 // Point to the component portion of the name
174 pConnection->ComponentName.Length = 0;
175 pConnection->ComponentName.MaximumLength = 0;
177 pConnection->ComponentName.Buffer = &pConnection->RemoteName.Buffer[ (pConnection->RemoteName.Length/sizeof( WCHAR)) - 1];
179 while( pConnection->ComponentName.Length <= pConnection->RemoteName.Length)
182 if( pConnection->ComponentName.Buffer[ 0] == L'\\')
185 pConnection->ComponentName.Buffer++;
190 pConnection->ComponentName.Length += sizeof( WCHAR);
191 pConnection->ComponentName.MaximumLength += sizeof( WCHAR);
193 pConnection->ComponentName.Buffer--;
197 // Go initialize the information about the connection
200 AFSInitializeConnectionInfo( pConnection,
204 // Store away the flags for the connection
207 pConnection->Flags = Flags;
210 // Insert the entry into our list. If this is a server
211 // connection then add it to the enumeration list, otherwise
212 // find the server name for this connection
215 if( DisplayType == RESOURCEDISPLAYTYPE_SERVER)
218 if( pRDRDevExt->Specific.RDR.ProviderEnumerationList == NULL)
221 pRDRDevExt->Specific.RDR.ProviderEnumerationList = pConnection;
227 // Get the end of the list
230 pLastConnection = pRDRDevExt->Specific.RDR.ProviderEnumerationList;
232 while( pLastConnection->fLink != NULL)
235 pLastConnection = pLastConnection->fLink;
238 pLastConnection->fLink = pConnection;
241 else if( pServerConnection != NULL)
244 if( pServerConnection->EnumerationList == NULL)
247 pServerConnection->EnumerationList = pConnection;
253 // Get the end of the list
256 pLastConnection = pServerConnection->EnumerationList;
258 while( pLastConnection->fLink != NULL)
261 pLastConnection = pLastConnection->fLink;
264 pLastConnection->fLink = pConnection;
270 AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
277 AFSInitializeConnectionInfo( IN AFSProviderConnectionCB *Connection,
278 IN ULONG DisplayType)
281 NTSTATUS ntStatus = STATUS_SUCCESS;
282 UNICODE_STRING uniName, uniComponentName, uniRemainingName;
287 uniName = Connection->RemoteName;
290 // Strip of the double leading slash if there is one
293 if( uniName.Buffer[ 0] == L'\\' &&
294 uniName.Buffer[ 1] == L'\\')
297 uniName.Buffer = &uniName.Buffer[ 1];
299 uniName.Length -= sizeof( WCHAR);
303 FsRtlDissectName( uniName,
308 // Initialize the information for the connection
309 // First, if this is the server only then mark it accordingly
312 if( uniRemainingName.Length == 0 ||
313 DisplayType == RESOURCEDISPLAYTYPE_SERVER)
316 Connection->Type = RESOURCETYPE_DISK;
318 Connection->Scope = RESOURCE_GLOBALNET;
320 Connection->DisplayType = RESOURCEDISPLAYTYPE_SERVER;
322 Connection->Usage = RESOURCEUSAGE_CONTAINER;
324 Connection->Comment.Length = 20;
325 Connection->Comment.MaximumLength = 22;
327 Connection->Comment.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
328 Connection->Comment.MaximumLength,
329 AFS_NETWORK_PROVIDER_7_TAG);
331 if( Connection->Comment.Buffer != NULL)
334 RtlZeroMemory( Connection->Comment.Buffer,
335 Connection->Comment.MaximumLength);
337 RtlCopyMemory( Connection->Comment.Buffer,
344 Connection->Comment.Length = 0;
345 Connection->Comment.MaximumLength = 0;
348 try_return( ntStatus);
351 uniName = uniRemainingName;
353 FsRtlDissectName( uniName,
357 if( uniRemainingName.Length == 0 ||
358 uniRemainingName.Buffer == NULL ||
359 DisplayType == RESOURCEDISPLAYTYPE_SHARE)
362 Connection->Type = RESOURCETYPE_DISK;
364 Connection->DisplayType = RESOURCEDISPLAYTYPE_SHARE;
366 Connection->Usage = RESOURCEUSAGE_CONNECTABLE;
368 if( Connection->LocalName != L'\0')
371 Connection->Usage |= RESOURCEUSAGE_ATTACHED;
373 Connection->Scope = RESOURCE_CONNECTED;
378 Connection->Scope = RESOURCE_GLOBALNET;
381 Connection->Comment.Length = 18;
382 Connection->Comment.MaximumLength = 20;
384 Connection->Comment.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
385 Connection->Comment.MaximumLength,
386 AFS_NETWORK_PROVIDER_8_TAG);
388 if( Connection->Comment.Buffer != NULL)
391 RtlZeroMemory( Connection->Comment.Buffer,
392 Connection->Comment.MaximumLength);
394 RtlCopyMemory( Connection->Comment.Buffer,
401 Connection->Comment.Length = 0;
402 Connection->Comment.MaximumLength = 0;
405 try_return( ntStatus);
409 // This is a sub directory within a share
412 Connection->Type = RESOURCETYPE_DISK;
414 Connection->DisplayType = RESOURCEDISPLAYTYPE_DIRECTORY;
416 Connection->Usage = RESOURCEUSAGE_CONNECTABLE;
418 if( Connection->LocalName != L'\0')
421 Connection->Usage |= RESOURCEUSAGE_ATTACHED;
424 Connection->Scope = RESOURCE_CONNECTED;
426 Connection->Comment.Length = 26;
427 Connection->Comment.MaximumLength = 28;
429 Connection->Comment.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
430 Connection->Comment.MaximumLength,
431 AFS_NETWORK_PROVIDER_9_TAG);
433 if( Connection->Comment.Buffer != NULL)
436 RtlZeroMemory( Connection->Comment.Buffer,
437 Connection->Comment.MaximumLength);
439 RtlCopyMemory( Connection->Comment.Buffer,
446 Connection->Comment.Length = 0;
447 Connection->Comment.MaximumLength = 0;