Windows: NP RemoteName Length checks
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSNetworkProviderSupport.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011, 2015 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
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
13  *   notice,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
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.
21  *
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.
33  */
34
35 //
36 // File: AFSNetworkProviderSupport.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 NTSTATUS
42 AFSAddConnection( IN AFSNetworkProviderConnectionCB *ConnectCB,
43                   IN OUT PULONG ResultStatus,
44                   IN OUT ULONG_PTR *ReturnOutputBufferLength)
45 {
46
47     NTSTATUS ntStatus = STATUS_SUCCESS;
48     AFSProviderConnectionCB *pConnection = NULL, *pLastConnection = NULL;
49     UNICODE_STRING uniRemoteName;
50     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
51
52     __Enter
53     {
54
55         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
56                       AFS_TRACE_LEVEL_VERBOSE,
57                       "AFSAddConnection Acquiring AFSProviderListLock lock %p EXCL %08lX\n",
58                       &pRDRDevExt->Specific.RDR.ProviderListLock,
59                       PsGetCurrentThread()));
60
61         ntStatus = AFSGetAuthenticationId(&ConnectCB->AuthenticationId);
62
63         if ( !NT_SUCCESS( ntStatus))
64         {
65
66             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
67                           AFS_TRACE_LEVEL_ERROR,
68                           "AFSAddConnection Unable to retrieve authentication id %08lX\n",
69                           ntStatus));
70
71             return ntStatus;
72         }
73
74         AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
75                       AFS_TRACE_LEVEL_VERBOSE,
76                       "AFSAddConnection Retrieved authentication id %I64X\n",
77                       ConnectCB->AuthenticationId.QuadPart));
78
79         AFSAcquireExcl( &pRDRDevExt->Specific.RDR.ProviderListLock,
80                         TRUE);
81
82         //
83         // Look for the connection
84         //
85
86         uniRemoteName.Length = (USHORT)ConnectCB->RemoteNameLength;
87         uniRemoteName.MaximumLength = uniRemoteName.Length;
88
89         uniRemoteName.Buffer = ConnectCB->RemoteName;
90
91         //
92         // Strip off any trailing slashes
93         //
94
95         if( uniRemoteName.Length >= sizeof( WCHAR)
96             && uniRemoteName.Buffer[ (uniRemoteName.Length/sizeof( WCHAR)) - 1] == L'\\')
97         {
98
99             uniRemoteName.Length -= sizeof( WCHAR);
100         }
101
102         pConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
103
104         while( pConnection != NULL)
105         {
106
107             if( pConnection->LocalName == ConnectCB->LocalName &&
108                 pConnection->AuthenticationId.QuadPart == ConnectCB->AuthenticationId.QuadPart &&
109                 RtlCompareUnicodeString( &uniRemoteName,
110                                          &pConnection->RemoteName,
111                                          TRUE) == 0)
112             {
113
114                 break;
115             }
116
117             pConnection = pConnection->fLink;
118         }
119
120         if( pConnection != NULL)
121         {
122
123             if( ConnectCB->LocalName != L'\0')
124             {
125
126                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
127                               AFS_TRACE_LEVEL_VERBOSE,
128                               "AFSAddConnection ALREADY_CONNECTED remote name %wZ Local %C authentication id %I64X\n",
129                               &uniRemoteName,
130                               ConnectCB->LocalName,
131                               ConnectCB->AuthenticationId.QuadPart));
132
133                 *ResultStatus = WN_ALREADY_CONNECTED;
134             }
135             else
136             {
137
138                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
139                               AFS_TRACE_LEVEL_VERBOSE,
140                               "AFSAddConnection ALREADY_CONNECTED remote name %wZ Local (NULL) authentication id %I64X\n",
141                               &uniRemoteName,
142                               ConnectCB->AuthenticationId.QuadPart));
143
144                 *ResultStatus = WN_SUCCESS;
145             }
146
147             *ReturnOutputBufferLength = sizeof( ULONG);
148
149             try_return( ntStatus = STATUS_SUCCESS);
150         }
151
152         //
153         // Validate the remote name
154         //
155
156         if( uniRemoteName.Length > 2 * sizeof( WCHAR) &&
157             uniRemoteName.Buffer[ 0] == L'\\' &&
158             uniRemoteName.Buffer[ 1] == L'\\')
159         {
160
161             uniRemoteName.Buffer = &uniRemoteName.Buffer[ 2];
162
163             uniRemoteName.Length -= (2 * sizeof( WCHAR));
164         }
165
166         if( uniRemoteName.Length >= AFSServerName.Length)
167         {
168
169             USHORT usLength = uniRemoteName.Length;
170
171             if (uniRemoteName.Buffer[AFSServerName.Length/sizeof( WCHAR)] != L'\\')
172             {
173
174                 if( ConnectCB->LocalName != L'\0')
175                 {
176
177                     AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
178                                   AFS_TRACE_LEVEL_VERBOSE,
179                                   "AFSAddConnection BAD_NETNAME 1 remote name %wZ Local %C authentication id %I64X\n",
180                                   &uniRemoteName,
181                                   ConnectCB->LocalName,
182                                   ConnectCB->AuthenticationId.QuadPart));
183                 }
184                 else
185                 {
186
187                     AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
188                                   AFS_TRACE_LEVEL_VERBOSE,
189                                   "AFSAddConnection BAD_NETNAME 1 remote name %wZ Local (NULL) authentication id %I64X\n",
190                                   &uniRemoteName,
191                                   ConnectCB->AuthenticationId.QuadPart));
192                 }
193
194                 *ResultStatus = WN_BAD_NETNAME;
195
196                 *ReturnOutputBufferLength = sizeof( ULONG);
197
198                 try_return( ntStatus = STATUS_SUCCESS);
199             }
200
201             uniRemoteName.Length = AFSServerName.Length;
202
203             if( RtlCompareUnicodeString( &AFSServerName,
204                                          &uniRemoteName,
205                                          TRUE) != 0)
206             {
207
208                 if( ConnectCB->LocalName != L'\0')
209                 {
210
211                     AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
212                                   AFS_TRACE_LEVEL_VERBOSE,
213                                   "AFSAddConnection BAD_NETNAME 2 remote name %wZ Local %C authentication id %I64X\n",
214                                   &uniRemoteName,
215                                   ConnectCB->LocalName,
216                                   ConnectCB->AuthenticationId.QuadPart));
217                 }
218                 else
219                 {
220
221                     AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
222                                   AFS_TRACE_LEVEL_VERBOSE,
223                                   "AFSAddConnection BAD_NETNAME 2 remote name %wZ Local (NULL) authentication id %I64X\n",
224                                   &uniRemoteName,
225                                   ConnectCB->AuthenticationId.QuadPart));
226                 }
227
228                 *ResultStatus = WN_BAD_NETNAME;
229
230                 *ReturnOutputBufferLength = sizeof( ULONG);
231
232                 try_return( ntStatus = STATUS_SUCCESS);
233             }
234
235             uniRemoteName.Length = usLength;
236         }
237         else
238         {
239
240             if( ConnectCB->LocalName != L'\0')
241             {
242
243                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
244                               AFS_TRACE_LEVEL_VERBOSE,
245                               "AFSAddConnection BAD_NETNAME 3 remote name %wZ Local %C authentication id %I64X\n",
246                               &uniRemoteName,
247                               ConnectCB->LocalName,
248                               ConnectCB->AuthenticationId.QuadPart));
249             }
250             else
251             {
252
253                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
254                               AFS_TRACE_LEVEL_VERBOSE,
255                               "AFSAddConnection BAD_NETNAME 3 remote name %wZ Local (NULL) authentication id %I64X\n",
256                               &uniRemoteName,
257                               ConnectCB->AuthenticationId.QuadPart));
258             }
259
260             *ResultStatus = WN_BAD_NETNAME;
261
262             *ReturnOutputBufferLength = sizeof( ULONG);
263
264             try_return( ntStatus = STATUS_SUCCESS);
265         }
266
267         uniRemoteName.Length = (USHORT)ConnectCB->RemoteNameLength;
268         uniRemoteName.MaximumLength = uniRemoteName.Length;
269
270         uniRemoteName.Buffer = ConnectCB->RemoteName;
271
272         //
273         // Strip off any trailing slashes
274         //
275
276         if( uniRemoteName.Length >= sizeof( WCHAR)
277             && uniRemoteName.Buffer[ (uniRemoteName.Length/sizeof( WCHAR)) - 1] == L'\\')
278         {
279
280             uniRemoteName.Length -= sizeof( WCHAR);
281         }
282
283         //
284         // Allocate a new node and add it to our list
285         //
286
287         pConnection = (AFSProviderConnectionCB *)AFSExAllocatePoolWithTag( PagedPool,
288                                                                            sizeof( AFSProviderConnectionCB) +
289                                                                                             uniRemoteName.Length,
290                                                                            AFS_PROVIDER_CB);
291
292         if( pConnection == NULL)
293         {
294
295             *ResultStatus = WN_OUT_OF_MEMORY;
296
297             *ReturnOutputBufferLength = sizeof( ULONG);
298
299             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
300         }
301
302         RtlZeroMemory( pConnection,
303                        sizeof( AFSProviderConnectionCB) + uniRemoteName.Length);
304
305         pConnection->LocalName = ConnectCB->LocalName;
306
307         pConnection->RemoteName.Length = uniRemoteName.Length;
308         pConnection->RemoteName.MaximumLength = pConnection->RemoteName.Length;
309
310         pConnection->RemoteName.Buffer = (WCHAR *)((char *)pConnection + sizeof( AFSProviderConnectionCB));
311
312         RtlCopyMemory( pConnection->RemoteName.Buffer,
313                        uniRemoteName.Buffer,
314                        pConnection->RemoteName.Length);
315
316         pConnection->Type = ConnectCB->Type;
317
318         pConnection->AuthenticationId = ConnectCB->AuthenticationId;
319
320         if( ConnectCB->LocalName != L'\0')
321         {
322
323             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
324                           AFS_TRACE_LEVEL_VERBOSE,
325                           "AFSAddConnection Adding connection remote name %wZ Local %C authentication id %I64X\n",
326                           &uniRemoteName,
327                           ConnectCB->LocalName,
328                           ConnectCB->AuthenticationId.QuadPart));
329         }
330         else
331         {
332
333             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
334                           AFS_TRACE_LEVEL_VERBOSE,
335                           "AFSAddConnection Adding connection remote name %wZ Local (NULL) authentication id %I64X\n",
336                           &uniRemoteName,
337                           ConnectCB->AuthenticationId.QuadPart));
338         }
339
340         //
341         // Point to the component portion of the name
342         //
343
344         pConnection->ComponentName.Length = 0;
345         pConnection->ComponentName.MaximumLength = 0;
346
347         pConnection->ComponentName.Buffer = &pConnection->RemoteName.Buffer[ (pConnection->RemoteName.Length/sizeof( WCHAR)) - 1];
348
349         while( pConnection->ComponentName.Length <= pConnection->RemoteName.Length)
350         {
351
352             if( pConnection->ComponentName.Buffer[ 0] == L'\\')
353             {
354
355                 pConnection->ComponentName.Buffer++;
356
357                 break;
358             }
359
360             pConnection->ComponentName.Length += sizeof( WCHAR);
361             pConnection->ComponentName.MaximumLength += sizeof( WCHAR);
362
363             pConnection->ComponentName.Buffer--;
364         }
365
366         //
367         // Go initialize the information about the connection
368         //
369
370         AFSInitializeConnectionInfo( pConnection,
371                                      (ULONG)-1);
372
373         //
374         // Insert the entry into our list
375         //
376
377         if( pRDRDevExt->Specific.RDR.ProviderConnectionList == NULL)
378         {
379
380             pRDRDevExt->Specific.RDR.ProviderConnectionList = pConnection;
381         }
382         else
383         {
384
385             //
386             // Get the end of the list
387             //
388
389             pLastConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
390
391             while( pLastConnection->fLink != NULL)
392             {
393
394                 pLastConnection = pLastConnection->fLink;
395             }
396
397             pLastConnection->fLink = pConnection;
398         }
399
400         *ResultStatus = WN_SUCCESS;
401
402         *ReturnOutputBufferLength = sizeof( ULONG);
403
404 try_exit:
405
406         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
407
408     }
409
410     return ntStatus;
411 }
412
413 NTSTATUS
414 AFSCancelConnection( IN AFSNetworkProviderConnectionCB *ConnectCB,
415                      IN OUT AFSCancelConnectionResultCB *ConnectionResult,
416                      IN OUT ULONG_PTR *ReturnOutputBufferLength)
417 {
418
419     NTSTATUS ntStatus = STATUS_SUCCESS;
420     AFSProviderConnectionCB *pConnection = NULL, *pLastConnection = NULL;
421     UNICODE_STRING uniRemoteName;
422     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
423
424     __Enter
425     {
426
427         ConnectionResult->Version = AFS_NETWORKPROVIDER_INTERFACE_VERSION_1;
428
429         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
430                       AFS_TRACE_LEVEL_VERBOSE,
431                       "AFSCancelConnection Acquiring AFSProviderListLock lock %p EXCL %08lX\n",
432                       &pRDRDevExt->Specific.RDR.ProviderListLock,
433                       PsGetCurrentThread()));
434
435         ntStatus = AFSGetAuthenticationId(&ConnectCB->AuthenticationId);
436
437         if ( !NT_SUCCESS( ntStatus))
438         {
439
440             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
441                           AFS_TRACE_LEVEL_ERROR,
442                           "AFSCancelConnection Unable to retrieve authentication id %08lX\n",
443                           ntStatus));
444
445             return ntStatus;
446         }
447
448         AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
449                       AFS_TRACE_LEVEL_VERBOSE,
450                       "AFSCancelConnection Retrieved authentication id %I64X\n",
451                       ConnectCB->AuthenticationId.QuadPart));
452
453         AFSAcquireExcl( &pRDRDevExt->Specific.RDR.ProviderListLock,
454                         TRUE);
455
456         //
457         // Look for the connection
458         //
459
460         uniRemoteName.Length = (USHORT)ConnectCB->RemoteNameLength;
461         uniRemoteName.MaximumLength = uniRemoteName.Length;
462
463         uniRemoteName.Buffer = NULL;
464
465         if( uniRemoteName.Length > 0)
466         {
467
468             uniRemoteName.Buffer = ConnectCB->RemoteName;
469         }
470
471         pConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
472
473         while( pConnection != NULL)
474         {
475
476             if( ( ConnectCB->LocalName != L'\0' &&
477                   pConnection->LocalName == ConnectCB->LocalName)
478                 ||
479                 ( ConnectCB->LocalName == L'\0' &&
480                   pConnection->LocalName == L'\0' &&
481                   RtlCompareUnicodeString( &uniRemoteName,
482                                            &pConnection->RemoteName,
483                                            TRUE) == 0))
484             {
485
486                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
487                               AFS_TRACE_LEVEL_VERBOSE,
488                               "AFSCancelConnection Checking remote name %wZ to stored %wZ authentication id %I64X - %I64X\n",
489                               &uniRemoteName,
490                               &pConnection->RemoteName,
491                               ConnectCB->AuthenticationId.QuadPart,
492                               pConnection->AuthenticationId.QuadPart));
493
494                 if( ConnectCB->AuthenticationId.QuadPart == pConnection->AuthenticationId.QuadPart &&
495                     ( ConnectCB->LocalName == L'\0' ||
496                       RtlCompareUnicodeString( &uniRemoteName,
497                                                &pConnection->RemoteName,
498                                                TRUE) == 0))
499                 {
500
501                     break;
502                 }
503             }
504
505             pLastConnection = pConnection;
506
507             pConnection = pConnection->fLink;
508         }
509
510         if( pConnection == NULL)
511         {
512
513             ConnectionResult->Status = WN_NOT_CONNECTED;
514
515             *ReturnOutputBufferLength = sizeof( AFSCancelConnectionResultCB);
516
517             try_return( ntStatus);
518         }
519
520         if( pLastConnection == NULL)
521         {
522
523             pRDRDevExt->Specific.RDR.ProviderConnectionList = pConnection->fLink;
524         }
525         else
526         {
527
528             pLastConnection->fLink = pConnection->fLink;
529         }
530
531         if( pConnection->Comment.Buffer != NULL)
532         {
533
534             AFSExFreePoolWithTag( pConnection->Comment.Buffer, 0);
535         }
536
537         ConnectionResult->LocalName = pConnection->LocalName;
538
539         AFSExFreePoolWithTag( pConnection, AFS_PROVIDER_CB);
540
541         ConnectionResult->Status = WN_SUCCESS;
542
543         *ReturnOutputBufferLength = sizeof( AFSCancelConnectionResultCB);
544
545 try_exit:
546
547         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
548     }
549
550     return ntStatus;
551 }
552
553 NTSTATUS
554 AFSGetConnection( IN AFSNetworkProviderConnectionCB *ConnectCB,
555                   IN OUT WCHAR *RemoteName,
556                   IN ULONG RemoteNameBufferLength,
557                   IN OUT ULONG_PTR *ReturnOutputBufferLength)
558 {
559
560     NTSTATUS ntStatus = STATUS_SUCCESS;
561     AFSProviderConnectionCB *pConnection = NULL;
562     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
563
564     __Enter
565     {
566
567         ntStatus = AFSGetAuthenticationId(&ConnectCB->AuthenticationId);
568
569         if ( !NT_SUCCESS( ntStatus))
570         {
571
572             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
573                           AFS_TRACE_LEVEL_ERROR,
574                           "AFSGetConnection Unable to retrieve authentication id %08lX\n",
575                           ntStatus));
576
577             return ntStatus;
578         }
579
580         AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
581                       AFS_TRACE_LEVEL_VERBOSE,
582                       "AFSGetConnection Retrieved authentication id %I64X\n",
583                       ConnectCB->AuthenticationId.QuadPart));
584
585         if( ConnectCB->LocalName != L'\0')
586         {
587
588             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
589                           AFS_TRACE_LEVEL_VERBOSE,
590                           "AFSGetConnection Local %C authentication id %I64X\n",
591                           ConnectCB->LocalName,
592                           ConnectCB->AuthenticationId.QuadPart));
593         }
594         else
595         {
596
597             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
598                           AFS_TRACE_LEVEL_VERBOSE,
599                           "AFSGetConnection Local (NULL) authentication id %I64X\n",
600                           ConnectCB->AuthenticationId.QuadPart));
601         }
602
603         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
604                       AFS_TRACE_LEVEL_VERBOSE,
605                       "AFSGetConnection Acquiring AFSProviderListLock lock %p SHARED %08lX\n",
606                       &pRDRDevExt->Specific.RDR.ProviderListLock,
607                       PsGetCurrentThread()));
608
609         AFSAcquireShared( &pRDRDevExt->Specific.RDR.ProviderListLock,
610                           TRUE);
611
612         //
613         // Look for the connection
614         //
615
616         pConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
617
618         while( pConnection != NULL)
619         {
620
621             if( pConnection->LocalName != L'\0')
622             {
623
624                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
625                               AFS_TRACE_LEVEL_VERBOSE,
626                               "AFSGetConnection Comparing passed in %C to %C authentication id %I64X - %I64X\n",
627                               ConnectCB->LocalName,
628                               pConnection->LocalName,
629                               ConnectCB->AuthenticationId.QuadPart,
630                               pConnection->AuthenticationId.QuadPart));
631             }
632             else
633             {
634
635                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
636                               AFS_TRACE_LEVEL_VERBOSE,
637                               "AFSGetConnection Comparing passed in %C to (NULL) authentication id %I64X - %I64X\n",
638                               ConnectCB->LocalName,
639                               ConnectCB->AuthenticationId.QuadPart,
640                               pConnection->AuthenticationId.QuadPart));
641             }
642
643             if( pConnection->LocalName == ConnectCB->LocalName &&
644                 pConnection->AuthenticationId.QuadPart == ConnectCB->AuthenticationId.QuadPart)
645             {
646
647                 break;
648             }
649
650             pConnection = pConnection->fLink;
651         }
652
653         if( pConnection == NULL)
654         {
655
656             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
657                           AFS_TRACE_LEVEL_VERBOSE,
658                           "AFSGetConnection INVALID_PARAMETER\n"));
659
660             try_return( ntStatus = STATUS_INVALID_PARAMETER);
661         }
662
663         if( RemoteNameBufferLength < pConnection->RemoteName.Length)
664         {
665
666             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
667                           AFS_TRACE_LEVEL_VERBOSE,
668                           "AFSGetConnection INSUFFICIENT_RESOURCES\n"));
669
670             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
671         }
672
673         RtlCopyMemory( RemoteName,
674                        pConnection->RemoteName.Buffer,
675                        pConnection->RemoteName.Length);
676
677         *ReturnOutputBufferLength = pConnection->RemoteName.Length;
678
679 try_exit:
680
681         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
682     }
683
684     return ntStatus;
685 }
686
687 NTSTATUS
688 AFSListConnections( IN OUT AFSNetworkProviderConnectionCB *ConnectCB,
689                     IN ULONG ConnectionBufferLength,
690                     IN OUT ULONG_PTR *ReturnOutputBufferLength)
691 {
692
693     NTSTATUS ntStatus = STATUS_SUCCESS;
694     AFSProviderConnectionCB *pConnection = NULL, *pRootConnection = NULL;
695     ULONG ulCopiedLength = 0, ulRemainingLength = ConnectionBufferLength;
696     ULONG ulScope, ulType;
697     UNICODE_STRING uniRemoteName, uniServerName, uniShareName, uniRemainingPath;
698     BOOLEAN bGlobalEnumeration = FALSE;
699     ULONG       ulIndex = 0;
700     LARGE_INTEGER liAuthenticationID = {0,0};
701     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
702
703     __Enter
704     {
705
706         //
707         // Save off some data before moving on
708         //
709
710         ulScope = ConnectCB->Scope;
711
712         ulType = ConnectCB->Type;
713
714         ntStatus = AFSGetAuthenticationId(&ConnectCB->AuthenticationId);
715
716         if ( !NT_SUCCESS( ntStatus))
717         {
718
719             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
720                           AFS_TRACE_LEVEL_ERROR,
721                           "AFSListConnection Unable to retrieve authentication id %08lX\n",
722                           ntStatus));
723
724             return ntStatus;
725         }
726
727         AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
728                       AFS_TRACE_LEVEL_VERBOSE,
729                       "AFSListConnections Retrieved authentication id %I64X\n",
730                       ConnectCB->AuthenticationId.QuadPart));
731
732         liAuthenticationID.QuadPart = ConnectCB->AuthenticationId.QuadPart;
733
734         uniRemoteName.Length = 0;
735         uniRemoteName.MaximumLength = 0;
736         uniRemoteName.Buffer = NULL;
737
738         uniServerName.Length = 0;
739         uniServerName.MaximumLength = 0;
740         uniServerName.Buffer = NULL;
741
742         uniShareName.Length = 0;
743         uniShareName.MaximumLength = 0;
744         uniShareName.Buffer = NULL;
745
746         if( ConnectCB->RemoteNameLength > 0)
747         {
748
749             uniRemoteName.Length = (USHORT)ConnectCB->RemoteNameLength;
750             uniRemoteName.MaximumLength = uniRemoteName.Length + sizeof( WCHAR);
751
752             uniRemoteName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
753                                                                       uniRemoteName.MaximumLength,
754                                                                       AFS_NETWORK_PROVIDER_1_TAG);
755
756             if( uniRemoteName.Buffer == NULL)
757             {
758
759                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
760             }
761
762             RtlCopyMemory( uniRemoteName.Buffer,
763                            ConnectCB->RemoteName,
764                            uniRemoteName.Length);
765
766             if( uniRemoteName.Length >= 2 * sizeof( WCHAR)
767                 && uniRemoteName.Buffer[ 0] == L'\\'
768                 && uniRemoteName.Buffer[ 1] == L'\\')
769             {
770
771                 uniRemoteName.Buffer = &uniRemoteName.Buffer[ 1];
772
773                 uniRemoteName.Length -= sizeof( WCHAR);
774             }
775
776             if( uniRemoteName.Length >= sizeof( WCHAR)
777                 && uniRemoteName.Buffer[ (uniRemoteName.Length/sizeof( WCHAR)) - 1] == L'\\')
778             {
779
780                 uniRemoteName.Length -= sizeof( WCHAR);
781             }
782
783             FsRtlDissectName( uniRemoteName,
784                               &uniServerName,
785                               &uniRemainingPath);
786
787             uniRemoteName = uniRemainingPath;
788
789             if( uniRemoteName.Length > 0)
790             {
791
792                 FsRtlDissectName( uniRemoteName,
793                                   &uniShareName,
794                                   &uniRemainingPath);
795             }
796
797             //
798             // If this is an enumeration of the global share name then
799             // adjust it to be the server name itself
800             //
801
802             if( uniShareName.Length == 0)
803             {
804
805                 bGlobalEnumeration = TRUE;
806             }
807         }
808
809         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
810                       AFS_TRACE_LEVEL_VERBOSE,
811                       "AFSListConnections Acquiring AFSProviderListLock lock %p SHARED %08lX\n",
812                       &pRDRDevExt->Specific.RDR.ProviderListLock,
813                       PsGetCurrentThread()));
814
815         AFSAcquireShared( &pRDRDevExt->Specific.RDR.ProviderListLock,
816                           TRUE);
817
818         //
819         // If this is a globalnet enumeration with no name then enumerate the server list
820         //
821
822         if( ulScope == RESOURCE_GLOBALNET)
823         {
824
825             if( uniServerName.Buffer == NULL)
826             {
827
828                 pConnection = pRDRDevExt->Specific.RDR.ProviderEnumerationList;
829             }
830             else
831             {
832
833                 //
834                 // Go locate the root entry for the name passed in
835                 //
836
837                 if( bGlobalEnumeration)
838                 {
839
840                     if( pRDRDevExt->Specific.RDR.ProviderEnumerationList == NULL)
841                     {
842
843                         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
844
845                         try_return( ntStatus);
846                     }
847
848                     pConnection = pRDRDevExt->Specific.RDR.ProviderEnumerationList->EnumerationList;
849                 }
850                 else
851                 {
852
853                     pRootConnection = AFSLocateEnumRootEntry( &uniShareName);
854
855                     if( pRootConnection == NULL)
856                     {
857
858                         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
859
860                         try_return( ntStatus);
861                     }
862
863                     //
864                     // Need to handle these enumerations from the directory listing
865                     //
866
867                     ntStatus = AFSEnumerateConnection( ConnectCB,
868                                                        pRootConnection,
869                                                        ConnectionBufferLength,
870                                                        &ulCopiedLength);
871                 }
872             }
873         }
874         else
875         {
876
877             pConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
878         }
879
880         ulIndex = ConnectCB->CurrentIndex;
881
882         while( pConnection != NULL)
883         {
884
885             if( bGlobalEnumeration &&
886                 BooleanFlagOn( pConnection->Flags, AFS_CONNECTION_FLAG_GLOBAL_SHARE))
887             {
888
889                 pConnection = pConnection->fLink;
890
891                 continue;
892             }
893
894             if( ulScope != RESOURCE_GLOBALNET &&
895                 !BooleanFlagOn( pConnection->Usage, RESOURCEUSAGE_ATTACHED))
896             {
897
898                 pConnection = pConnection->fLink;
899
900                 continue;
901             }
902
903             if( pConnection->LocalName != L'\0')
904             {
905
906                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
907                               AFS_TRACE_LEVEL_VERBOSE,
908                               "AFSListConnections Processing entry %wZ %C authentication id %I64X - %I64X Scope %08lX\n",
909                               &pConnection->RemoteName,
910                               pConnection->LocalName,
911                               liAuthenticationID.QuadPart,
912                               pConnection->AuthenticationId.QuadPart,
913                               pConnection->Scope));
914             }
915             else
916             {
917
918                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
919                               AFS_TRACE_LEVEL_VERBOSE,
920                               "AFSListConnections Processing entry %wZ NULL LocalName authentication id %I64X - %I64X Scope %08lX\n",
921                               &pConnection->RemoteName,
922                               liAuthenticationID.QuadPart,
923                               pConnection->AuthenticationId.QuadPart,
924                               pConnection->Scope));
925             }
926
927             if( ulScope != RESOURCE_GLOBALNET &&
928                 pConnection->AuthenticationId.QuadPart != liAuthenticationID.QuadPart)
929             {
930
931                 pConnection = pConnection->fLink;
932
933                 continue;
934             }
935
936             if( ulIndex > 0)
937             {
938
939                 ulIndex--;
940
941                 pConnection = pConnection->fLink;
942
943                 continue;
944             }
945
946             if( ulRemainingLength < (ULONG)FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
947                                                          pConnection->RemoteName.Length +
948                                                          pConnection->Comment.Length)
949             {
950
951                 break;
952             }
953
954             ConnectCB->RemoteNameLength = pConnection->RemoteName.Length;
955
956             RtlCopyMemory( ConnectCB->RemoteName,
957                            pConnection->RemoteName.Buffer,
958                            pConnection->RemoteName.Length);
959
960             ConnectCB->LocalName = pConnection->LocalName;
961
962             ConnectCB->Type = pConnection->Type;
963
964             ConnectCB->Scope = pConnection->Scope;
965
966             if( !bGlobalEnumeration)
967             {
968
969                 ConnectCB->Scope = RESOURCE_CONNECTED;
970             }
971
972             ConnectCB->DisplayType = pConnection->DisplayType;
973
974             ConnectCB->Usage = pConnection->Usage;
975
976             ConnectCB->CommentLength = pConnection->Comment.Length;
977
978             if( pConnection->Comment.Length > 0)
979             {
980
981                 ConnectCB->CommentOffset = (ULONG)(FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
982                                                                         ConnectCB->RemoteNameLength);
983
984                 RtlCopyMemory( (void *)((char *)ConnectCB + ConnectCB->CommentOffset),
985                                pConnection->Comment.Buffer,
986                                ConnectCB->CommentLength);
987             }
988
989             ulCopiedLength += FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
990                                                     ConnectCB->RemoteNameLength +
991                                                     ConnectCB->CommentLength;
992
993             ulRemainingLength -= FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
994                                                     ConnectCB->RemoteNameLength +
995                                                     ConnectCB->CommentLength;
996
997             ConnectCB = (AFSNetworkProviderConnectionCB *)((char *)ConnectCB +
998                                                             FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
999                                                             ConnectCB->RemoteNameLength +
1000                                                             ConnectCB->CommentLength);
1001
1002             pConnection = pConnection->fLink;
1003         }
1004
1005         if( NT_SUCCESS( ntStatus))
1006         {
1007
1008             *ReturnOutputBufferLength = ulCopiedLength;
1009         }
1010
1011         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1012
1013 try_exit:
1014
1015         if( uniRemoteName.Buffer != NULL)
1016         {
1017
1018             AFSExFreePoolWithTag( uniRemoteName.Buffer, 0);
1019         }
1020     }
1021
1022     return ntStatus;
1023 }
1024
1025 void
1026 AFSInitializeConnectionInfo( IN AFSProviderConnectionCB *Connection,
1027                              IN ULONG DisplayType)
1028 {
1029
1030     NTSTATUS ntStatus = STATUS_SUCCESS;
1031     UNICODE_STRING uniName, uniComponentName, uniRemainingName;
1032
1033     __Enter
1034     {
1035
1036         uniName = Connection->RemoteName;
1037
1038         //
1039         // Strip off the double leading slash if there is one
1040         //
1041
1042         if( uniName.Length >= 2 * sizeof( WCHAR)
1043             && uniName.Buffer[ 0] == L'\\'
1044             && uniName.Buffer[ 1] == L'\\')
1045         {
1046
1047             uniName.Buffer = &uniName.Buffer[ 1];
1048
1049             uniName.Length -= sizeof( WCHAR);
1050         }
1051
1052
1053         FsRtlDissectName( uniName,
1054                           &uniComponentName,
1055                           &uniRemainingName);
1056
1057         //
1058         // Initialize the information for the connection
1059         // First, if this is the server only then mark it accordingly
1060         //
1061
1062         if( uniRemainingName.Length == 0 ||
1063             DisplayType == RESOURCEDISPLAYTYPE_SERVER)
1064         {
1065
1066             Connection->Type = RESOURCETYPE_DISK;
1067
1068             Connection->Scope = 0;
1069
1070             Connection->DisplayType = RESOURCEDISPLAYTYPE_SERVER;
1071
1072             Connection->Usage = RESOURCEUSAGE_CONTAINER;
1073
1074             Connection->Comment.Length = 20;
1075             Connection->Comment.MaximumLength = 22;
1076
1077             Connection->Comment.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1078                                                                             Connection->Comment.MaximumLength,
1079                                                                             AFS_NETWORK_PROVIDER_2_TAG);
1080
1081             if( Connection->Comment.Buffer != NULL)
1082             {
1083
1084                 RtlZeroMemory( Connection->Comment.Buffer,
1085                                Connection->Comment.MaximumLength);
1086
1087                 RtlCopyMemory( Connection->Comment.Buffer,
1088                                L"AFS Root",
1089                                16);
1090             }
1091             else
1092             {
1093
1094                 Connection->Comment.Length = 0;
1095                 Connection->Comment.MaximumLength = 0;
1096             }
1097
1098             try_return( ntStatus);
1099         }
1100
1101         uniName = uniRemainingName;
1102
1103         FsRtlDissectName( uniName,
1104                           &uniComponentName,
1105                           &uniRemainingName);
1106
1107         if( uniRemainingName.Length == 0 ||
1108             uniRemainingName.Buffer == NULL ||
1109             DisplayType == RESOURCEDISPLAYTYPE_SHARE)
1110         {
1111
1112             Connection->Type = RESOURCETYPE_DISK;
1113
1114             Connection->DisplayType = RESOURCEDISPLAYTYPE_SHARE;
1115
1116             Connection->Usage = RESOURCEUSAGE_CONNECTABLE;
1117
1118             if( Connection->LocalName != L'\0')
1119             {
1120
1121                 Connection->Usage |= RESOURCEUSAGE_ATTACHED;
1122
1123                 Connection->Scope = RESOURCE_CONNECTED;
1124             }
1125             else
1126             {
1127
1128                 Connection->Usage |= RESOURCEUSAGE_NOLOCALDEVICE;
1129
1130                 Connection->Scope = RESOURCE_GLOBALNET;
1131             }
1132
1133             Connection->Comment.Length = 18;
1134             Connection->Comment.MaximumLength = 20;
1135
1136             Connection->Comment.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1137                                                                             Connection->Comment.MaximumLength,
1138                                                                             AFS_NETWORK_PROVIDER_3_TAG);
1139
1140             if( Connection->Comment.Buffer != NULL)
1141             {
1142
1143                 RtlZeroMemory( Connection->Comment.Buffer,
1144                                Connection->Comment.MaximumLength);
1145
1146                 RtlCopyMemory( Connection->Comment.Buffer,
1147                                L"AFS Share",
1148                                18);
1149             }
1150             else
1151             {
1152
1153                 Connection->Comment.Length = 0;
1154                 Connection->Comment.MaximumLength = 0;
1155             }
1156
1157             try_return( ntStatus);
1158         }
1159
1160         //
1161         // This is a sub directory within a share
1162         //
1163
1164         Connection->Type = RESOURCETYPE_DISK;
1165
1166         Connection->DisplayType = RESOURCEDISPLAYTYPE_DIRECTORY;
1167
1168         Connection->Usage = RESOURCEUSAGE_CONNECTABLE;
1169
1170         if( Connection->LocalName != L'\0')
1171         {
1172
1173             Connection->Usage |= RESOURCEUSAGE_ATTACHED;
1174         }
1175         else
1176         {
1177
1178             Connection->Usage |= RESOURCEUSAGE_NOLOCALDEVICE;
1179         }
1180
1181         Connection->Scope = RESOURCE_CONNECTED;
1182
1183         Connection->Comment.Length = 26;
1184         Connection->Comment.MaximumLength = 28;
1185
1186         Connection->Comment.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1187                                                                         Connection->Comment.MaximumLength,
1188                                                                         AFS_NETWORK_PROVIDER_4_TAG);
1189
1190         if( Connection->Comment.Buffer != NULL)
1191         {
1192
1193             RtlZeroMemory( Connection->Comment.Buffer,
1194                            Connection->Comment.MaximumLength);
1195
1196             RtlCopyMemory( Connection->Comment.Buffer,
1197                            L"AFS Directory",
1198                            26);
1199         }
1200         else
1201         {
1202
1203             Connection->Comment.Length = 0;
1204             Connection->Comment.MaximumLength = 0;
1205         }
1206
1207 try_exit:
1208
1209         NOTHING;
1210     }
1211
1212     return;
1213 }
1214
1215 AFSProviderConnectionCB *
1216 AFSLocateEnumRootEntry( IN UNICODE_STRING *RemoteName)
1217 {
1218
1219     AFSProviderConnectionCB *pConnection = NULL;
1220     UNICODE_STRING uniRemoteName = *RemoteName;
1221     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1222
1223     __Enter
1224     {
1225
1226         if( pRDRDevExt->Specific.RDR.ProviderEnumerationList == NULL)
1227         {
1228
1229             try_return( pConnection);
1230         }
1231
1232         pConnection = pRDRDevExt->Specific.RDR.ProviderEnumerationList->EnumerationList;
1233
1234         while( pConnection != NULL)
1235         {
1236
1237             if( RtlCompareUnicodeString( &uniRemoteName,
1238                                          &pConnection->ComponentName,
1239                                          TRUE) == 0)
1240             {
1241
1242                 break;
1243             }
1244
1245             pConnection = pConnection->fLink;
1246         }
1247
1248 try_exit:
1249
1250         NOTHING;
1251     }
1252
1253     return pConnection;
1254 }
1255
1256 NTSTATUS
1257 AFSEnumerateConnection( IN OUT AFSNetworkProviderConnectionCB *ConnectCB,
1258                         IN AFSProviderConnectionCB *RootConnection,
1259                         IN ULONG BufferLength,
1260                         OUT PULONG CopiedLength)
1261 {
1262
1263     NTSTATUS ntStatus = STATUS_SUCCESS;
1264     ULONG ulCRC = 0, ulCopiedLength = 0;
1265     AFSDirectoryCB *pShareDirEntry = NULL;
1266     AFSDirectoryCB *pDirEntry = NULL, *pTargetDirEntry = NULL;
1267     ULONG ulIndex = 0;
1268     LONG lCount;
1269
1270     __Enter
1271     {
1272
1273         if( AFSGlobalRoot == NULL)
1274         {
1275
1276             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1277                           AFS_TRACE_LEVEL_ERROR,
1278                           "AFSEnumerateConnection Global root not yet initialized\n"));
1279
1280             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1281         }
1282
1283         ulCRC = AFSGenerateCRC( &RootConnection->ComponentName,
1284                                 FALSE);
1285
1286         //
1287         // Grab our tree lock shared
1288         //
1289
1290         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1291                       AFS_TRACE_LEVEL_VERBOSE,
1292                       "AFSEnumerateConnection Acquiring GlobalRoot DirectoryNodeHdr.TreeLock lock %p SHARED %08lX\n",
1293                       AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
1294                       PsGetCurrentThread()));
1295
1296         AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
1297                           TRUE);
1298
1299         //
1300         // Locate the dir entry for this node
1301         //
1302
1303         ntStatus = AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1304                                                    ulCRC,
1305                                                    &pShareDirEntry);
1306
1307         if( pShareDirEntry == NULL ||
1308             !NT_SUCCESS( ntStatus))
1309         {
1310
1311             //
1312             // Perform a case insensitive search
1313             //
1314
1315             ulCRC = AFSGenerateCRC( &RootConnection->ComponentName,
1316                                     TRUE);
1317
1318             ntStatus = AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1319                                                          ulCRC,
1320                                                          &pShareDirEntry);
1321
1322             if( pShareDirEntry == NULL ||
1323                 !NT_SUCCESS( ntStatus))
1324             {
1325
1326                 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
1327
1328                 try_return( ntStatus);
1329             }
1330         }
1331
1332         lCount = InterlockedIncrement( &pShareDirEntry->DirOpenReferenceCount);
1333
1334         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1335                       AFS_TRACE_LEVEL_VERBOSE,
1336                       "AFSEnumerateConnection1 Increment count on %wZ DE %p Ccb %p Cnt %d\n",
1337                       &pShareDirEntry->NameInformation.FileName,
1338                       pShareDirEntry,
1339                       NULL,
1340                       lCount));
1341
1342         AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
1343
1344         //
1345         // Setup the request to evaluate the entry
1346         // On success, pTargetDirEntry has the DirOpenReferenceCount held
1347         //
1348
1349         ntStatus = AFSEvaluateRootEntry( pShareDirEntry,
1350                                          &pTargetDirEntry);
1351
1352         if( !NT_SUCCESS( ntStatus))
1353         {
1354
1355             try_return( ntStatus);
1356         }
1357
1358         AFSAcquireShared( pTargetDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1359                           TRUE);
1360
1361         //
1362         // Enumerate the content
1363         //
1364
1365         pDirEntry = pTargetDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
1366
1367         ulIndex = ConnectCB->CurrentIndex;
1368
1369         while( pDirEntry != NULL)
1370         {
1371
1372             if( ulIndex > 0)
1373             {
1374
1375                 ulIndex--;
1376
1377                 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
1378
1379                 continue;
1380             }
1381
1382             if( BufferLength < (ULONG)FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1383                                                                pDirEntry->NameInformation.FileName.Length)
1384             {
1385
1386                 break;
1387             }
1388
1389             ConnectCB->LocalName = L'\0';
1390
1391             ConnectCB->RemoteNameLength = pDirEntry->NameInformation.FileName.Length;
1392
1393             RtlCopyMemory( ConnectCB->RemoteName,
1394                            pDirEntry->NameInformation.FileName.Buffer,
1395                            pDirEntry->NameInformation.FileName.Length);
1396
1397             ConnectCB->Type = RESOURCETYPE_DISK;
1398
1399             ConnectCB->Scope = RESOURCE_CONNECTED;
1400
1401             if( BooleanFlagOn( pDirEntry->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
1402             {
1403
1404                 ConnectCB->DisplayType = RESOURCEDISPLAYTYPE_DIRECTORY;
1405             }
1406             else
1407             {
1408
1409                 ConnectCB->DisplayType = RESOURCEDISPLAYTYPE_FILE;
1410             }
1411
1412             ConnectCB->Usage = 0;
1413
1414             ConnectCB->CommentLength = 0;
1415
1416             ulCopiedLength += FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1417                                                     pDirEntry->NameInformation.FileName.Length;
1418
1419             BufferLength -= FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1420                                                     pDirEntry->NameInformation.FileName.Length;
1421
1422             ConnectCB = (AFSNetworkProviderConnectionCB *)((char *)ConnectCB +
1423                                                             FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1424                                                             ConnectCB->RemoteNameLength);
1425
1426             pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
1427         }
1428
1429         //
1430         // Release the DirOpenReferenceCount obtained from AFSEvaluateRootEntry
1431         //
1432
1433         lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount);
1434
1435         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1436                       AFS_TRACE_LEVEL_VERBOSE,
1437                       "AFSEnumerateConnection Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1438                       &pTargetDirEntry->NameInformation.FileName,
1439                       pTargetDirEntry,
1440                       NULL,
1441                       lCount));
1442
1443         ASSERT( lCount >= 0);
1444
1445         *CopiedLength = ulCopiedLength;
1446
1447         AFSReleaseResource( pTargetDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1448
1449 try_exit:
1450
1451         if( pShareDirEntry != NULL)
1452         {
1453             lCount = InterlockedDecrement( &pShareDirEntry->DirOpenReferenceCount);
1454
1455             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1456                           AFS_TRACE_LEVEL_VERBOSE,
1457                           "AFSEnumerateConnection1 Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1458                           &pShareDirEntry->NameInformation.FileName,
1459                           pShareDirEntry,
1460                           NULL,
1461                           lCount));
1462
1463             ASSERT( lCount >= 0);
1464         }
1465     }
1466
1467     return ntStatus;
1468 }
1469
1470 NTSTATUS
1471 AFSGetConnectionInfo( IN AFSNetworkProviderConnectionCB *ConnectCB,
1472                       IN ULONG BufferLength,
1473                       IN OUT ULONG_PTR *ReturnOutputBufferLength)
1474 {
1475
1476     NTSTATUS ntStatus = STATUS_SUCCESS;
1477     AFSProviderConnectionCB *pConnection = NULL, *pBestMatch = NULL;
1478     UNICODE_STRING uniRemoteName, uniServerName, uniShareName, uniRemainingPath, uniFullName, uniRemainingPathLocal;
1479     BOOLEAN bEnumerationEntry = FALSE;
1480     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1481
1482     __Enter
1483     {
1484
1485         uniServerName.Length = 0;
1486         uniServerName.MaximumLength = 0;
1487         uniServerName.Buffer = NULL;
1488
1489         uniShareName.Length = 0;
1490         uniShareName.MaximumLength = 0;
1491         uniShareName.Buffer = NULL;
1492
1493         uniRemainingPathLocal.Length = 0;
1494         uniRemainingPathLocal.MaximumLength = 0;
1495         uniRemainingPathLocal.Buffer = NULL;
1496
1497         uniRemoteName.Length = (USHORT)ConnectCB->RemoteNameLength;
1498         uniRemoteName.MaximumLength = uniRemoteName.Length + sizeof( WCHAR);
1499         uniRemoteName.Buffer = (WCHAR *)ConnectCB->RemoteName;
1500
1501         ntStatus = AFSGetAuthenticationId(&ConnectCB->AuthenticationId);
1502
1503         if ( !NT_SUCCESS( ntStatus))
1504         {
1505
1506             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1507                           AFS_TRACE_LEVEL_ERROR,
1508                           "AFSGetConnectionInfo Unable to retrieve authentication id %08lX\n",
1509                           ntStatus));
1510
1511             return ntStatus;
1512         }
1513
1514         AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1515                       AFS_TRACE_LEVEL_VERBOSE,
1516                       "AFSGetConnectionInfo Retrieved authentication id %I64X\n",
1517                       ConnectCB->AuthenticationId.QuadPart));
1518
1519         if( ConnectCB->LocalName != L'\0')
1520         {
1521
1522             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1523                           AFS_TRACE_LEVEL_VERBOSE,
1524                           "AFSGetConnectionInfo remote name %wZ Local %C authentication id %I64X\n",
1525                           &uniRemoteName,
1526                           ConnectCB->LocalName,
1527                           ConnectCB->AuthenticationId.QuadPart));
1528         }
1529         else
1530         {
1531
1532             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1533                           AFS_TRACE_LEVEL_VERBOSE,
1534                           "AFSGetConnectionInfo remote name %wZ Local (NULL) authentication id %I64X\n",
1535                           &uniRemoteName,
1536                           ConnectCB->AuthenticationId.QuadPart));
1537         }
1538
1539         if( AFSGlobalRoot == NULL)
1540         {
1541
1542             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1543                           AFS_TRACE_LEVEL_ERROR,
1544                           "AFSGetConnectionInfo Global root not yet initialized\n"));
1545
1546             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1547         }
1548
1549         uniFullName = uniRemoteName;
1550
1551         if( uniRemoteName.Length >= 2 * sizeof( WCHAR)
1552             && uniRemoteName.Buffer[ 0] == L'\\'
1553             && uniRemoteName.Buffer[ 1] == L'\\')
1554         {
1555
1556             uniRemoteName.Buffer = &uniRemoteName.Buffer[ 1];
1557
1558             uniRemoteName.Length -= sizeof( WCHAR);
1559         }
1560
1561         if( uniRemoteName.Length >= sizeof( WCHAR)
1562             && uniRemoteName.Buffer[ (uniRemoteName.Length/sizeof( WCHAR)) - 1] == L'\\')
1563         {
1564
1565             uniRemoteName.Length -= sizeof( WCHAR);
1566
1567             uniFullName.Length -= sizeof( WCHAR);
1568         }
1569
1570         AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1571                       AFS_TRACE_LEVEL_VERBOSE,
1572                       "AFSGetConnectionInfo Processing name %wZ\n",
1573                       &uniFullName));
1574
1575         FsRtlDissectName( uniRemoteName,
1576                           &uniServerName,
1577                           &uniRemainingPath);
1578
1579         uniRemoteName = uniRemainingPath;
1580
1581         if( uniRemoteName.Length > 0)
1582         {
1583
1584             FsRtlDissectName( uniRemoteName,
1585                               &uniShareName,
1586                               &uniRemainingPath);
1587         }
1588
1589         if( RtlCompareUnicodeString( &uniServerName,
1590                                      &AFSServerName,
1591                                      TRUE) != 0)
1592         {
1593
1594             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1595         }
1596
1597         if ( uniRemainingPath.Length > 0 )
1598         {
1599
1600             //
1601             // Add back in the leading \ since it was stripped off above
1602             //
1603
1604             uniRemainingPath.Length += sizeof( WCHAR);
1605             if( uniRemainingPath.Length > uniRemainingPath.MaximumLength)
1606             {
1607                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
1608             }
1609
1610             uniRemainingPath.Buffer--;
1611
1612             uniRemainingPathLocal.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1613                                                                               uniRemainingPath.Length,
1614                                                                               AFS_NETWORK_PROVIDER_5_TAG);
1615
1616             if( uniRemainingPathLocal.Buffer == NULL)
1617             {
1618
1619                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1620                               AFS_TRACE_LEVEL_VERBOSE,
1621                               "AFSGetConnectionInfo INSUFFICIENT_RESOURCES\n"));
1622
1623                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1624             }
1625
1626             uniRemainingPathLocal.MaximumLength = uniRemainingPath.Length;
1627             uniRemainingPathLocal.Length = uniRemainingPath.Length;
1628
1629             RtlCopyMemory( uniRemainingPathLocal.Buffer,
1630                            uniRemainingPath.Buffer,
1631                            uniRemainingPath.Length);
1632         }
1633
1634         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1635                       AFS_TRACE_LEVEL_VERBOSE,
1636                       "AFSGetConnectionInfo Acquiring AFSProviderListLock lock %p SHARED %08lX\n",
1637                       &pRDRDevExt->Specific.RDR.ProviderListLock,
1638                       PsGetCurrentThread()));
1639
1640         AFSAcquireShared( &pRDRDevExt->Specific.RDR.ProviderListLock,
1641                           TRUE);
1642
1643         //
1644         // If this is the server then return information about the
1645         // server entry
1646         //
1647
1648         if( uniShareName.Length == 0 &&
1649             RtlCompareUnicodeString( &uniServerName,
1650                                      &AFSServerName,
1651                                      TRUE) == 0)
1652         {
1653
1654             pConnection = pRDRDevExt->Specific.RDR.ProviderEnumerationList;
1655         }
1656         else
1657         {
1658
1659             USHORT usNameLen = 0, usMaxNameLen = 0;
1660
1661             //
1662             // AFSGetConnectionInfo() is called to generate responses for
1663             // NPGetResourceInformation and NPGetConnectionPerformance.
1664             // The former can be called with a Connection->RemoteName that
1665             // consists of \\server\share\dir1\dir2\...\dirN where one or
1666             // all of the directories do not have to be processed by the
1667             // network provider.  For example, one of the directories might
1668             // be a reparse point that redirects to another network provider.
1669             // It might also be the case that a directory might be in the
1670             // \\afs file namespace but not be accessible with the current
1671             // credentials.  That doesn't make the connection invalid.
1672             // As such the network provider is not required to validate the
1673             // entire RemoteName.  This can result in false positives.
1674             //
1675
1676             pConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
1677
1678             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1679                           AFS_TRACE_LEVEL_VERBOSE,
1680                           "AFSGetConnectionInfo Searching for full name %wZ\n",
1681                           &uniFullName));
1682
1683             while (pConnection != NULL)
1684             {
1685
1686                 //
1687                 // A partial match can be valid but it must occur on a
1688                 // component boundary.
1689                 //
1690
1691                 if (pConnection->AuthenticationId.QuadPart == ConnectCB->AuthenticationId.QuadPart &&
1692                      usMaxNameLen < pConnection->RemoteName.Length &&
1693                      (pConnection->RemoteName.Length == uniFullName.Length ||
1694                        pConnection->RemoteName.Length < uniFullName.Length &&
1695                        (uniFullName.Buffer[pConnection->RemoteName.Length/sizeof(WCHAR)] == L'\\' ||
1696                          uniFullName.Buffer[pConnection->RemoteName.Length/sizeof(WCHAR)] == L'/')))
1697                 {
1698
1699                     usNameLen = uniFullName.Length;
1700
1701                     uniFullName.Length = pConnection->RemoteName.Length;
1702
1703                     if (RtlCompareUnicodeString( &uniFullName,
1704                                                  &pConnection->RemoteName,
1705                                                  TRUE) == 0)
1706                     {
1707
1708                         usMaxNameLen = pConnection->RemoteName.Length;
1709
1710                         pBestMatch = pConnection;
1711
1712                         AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1713                                       AFS_TRACE_LEVEL_VERBOSE,
1714                                       "AFSGetConnectionInfo Found match for %wZ\n",
1715                                       &pConnection->RemoteName));
1716                     }
1717
1718                     uniFullName.Length = usNameLen;
1719                 }
1720
1721                 pConnection = pConnection->fLink;
1722             }
1723
1724             pConnection = pBestMatch;
1725
1726             if( pConnection != NULL)
1727             {
1728
1729                 bEnumerationEntry = TRUE;
1730
1731                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1732                               AFS_TRACE_LEVEL_VERBOSE,
1733                               "AFSGetConnectionInfo Using best match for %wZ\n",
1734                               &pConnection->RemoteName));
1735             }
1736             else
1737             {
1738
1739                 //
1740                 // Locate the entry for the share
1741                 //
1742
1743                 pConnection = AFSLocateEnumRootEntry( &uniShareName);
1744
1745                 if (pConnection != NULL)
1746                 {
1747
1748                     AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1749                                   AFS_TRACE_LEVEL_VERBOSE,
1750                                   "AFSGetConnectionInfo Using share connection %wZ\n",
1751                                   &pConnection->RemoteName));
1752                 }
1753             }
1754         }
1755
1756         if( pConnection == NULL)
1757         {
1758             UNICODE_STRING uniFullName;
1759             AFSDirEnumEntry *pDirEnumEntry = NULL;
1760
1761             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1762                           AFS_TRACE_LEVEL_VERBOSE,
1763                           "AFSGetConnectionInfo No connection for full name %wZ\n",
1764                           &uniFullName));
1765
1766             //
1767             // Drop the lock, we will pick it up again later
1768             //
1769
1770             AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1771
1772             //
1773             // OK, ask the CM about this component name
1774             //
1775
1776             ntStatus = AFSEvaluateTargetByName( NULL,
1777                                                 &AFSGlobalRoot->ObjectInformation,
1778                                                 &uniShareName,
1779                                                 0,
1780                                                 &pDirEnumEntry);
1781
1782             if( !NT_SUCCESS( ntStatus))
1783             {
1784
1785                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1786                               AFS_TRACE_LEVEL_VERBOSE,
1787                               "AFSGetConnectionInfo Evaluation Failed share name %wZ\n",
1788                               uniShareName));
1789
1790                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1791
1792             }
1793
1794             //
1795             // Don't need this
1796             //
1797
1798             AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_3_TAG);
1799
1800             //
1801             // The share name is valid
1802             // Allocate a new node and add it to our list
1803             //
1804             uniFullName.MaximumLength = PAGE_SIZE;
1805             uniFullName.Length = 0;
1806
1807             uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1808                                                                     uniFullName.MaximumLength,
1809                                                                     AFS_NETWORK_PROVIDER_6_TAG);
1810
1811             if( uniFullName.Buffer == NULL)
1812             {
1813
1814                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1815                               AFS_TRACE_LEVEL_VERBOSE,
1816                               "AFSGetConnectionInfo INSUFFICIENT_RESOURCES\n"));
1817
1818                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1819             }
1820
1821             uniFullName.Buffer[ 0] = L'\\';
1822             uniFullName.Buffer[ 1] = L'\\';
1823
1824             uniFullName.Length = 2 * sizeof( WCHAR);
1825
1826             RtlCopyMemory( &uniFullName.Buffer[ 2],
1827                            AFSServerName.Buffer,
1828                            AFSServerName.Length);
1829
1830             uniFullName.Length += AFSServerName.Length;
1831
1832             uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)] = L'\\';
1833
1834             uniFullName.Length += sizeof( WCHAR);
1835
1836             RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
1837                            uniShareName.Buffer,
1838                            uniShareName.Length);
1839
1840             uniFullName.Length += uniShareName.Length;
1841
1842             AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
1843                             TRUE);
1844
1845             ntStatus = AFSAddConnectionEx( &uniFullName,
1846                                            RESOURCEDISPLAYTYPE_SHARE,
1847                                            0);
1848
1849             AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
1850
1851             AFSExFreePoolWithTag( uniFullName.Buffer, 0);
1852
1853             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1854                           AFS_TRACE_LEVEL_VERBOSE,
1855                           "AFSGetConnectionInfo Acquiring AFSProviderListLock lock %p SHARED %08lX\n",
1856                           &pRDRDevExt->Specific.RDR.ProviderListLock,
1857                           PsGetCurrentThread()));
1858
1859             AFSAcquireShared( &pRDRDevExt->Specific.RDR.ProviderListLock,
1860                               TRUE);
1861
1862             if ( NT_SUCCESS( ntStatus) )
1863             {
1864                 //
1865                 // Once again, locate the entry for the share we just created
1866                 //
1867
1868                 pConnection = AFSLocateEnumRootEntry( &uniShareName);
1869             }
1870
1871         }
1872
1873         if( pConnection == NULL)
1874         {
1875
1876             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1877                           AFS_TRACE_LEVEL_ERROR,
1878                           "AFSGetConnectionInfo Failed to locate entry for full name %wZ\n",
1879                           &uniFullName));
1880
1881             AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1882
1883             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1884         }
1885
1886         //
1887         // Fill in the returned connection info block
1888         //
1889
1890         if( BufferLength < (ULONG)FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1891                                                 pConnection->RemoteName.Length +
1892                                                 pConnection->Comment.Length +
1893                                                 uniRemainingPath.Length)
1894         {
1895
1896             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1897                           AFS_TRACE_LEVEL_VERBOSE,
1898                           "AFSGetConnectionInfo Buffer too small for full name %wZ\n",
1899                           &uniFullName));
1900
1901             AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1902
1903             try_return( ntStatus = STATUS_BUFFER_OVERFLOW);
1904         }
1905
1906         AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1907                       AFS_TRACE_LEVEL_VERBOSE,
1908                       "AFSGetConnectionInfo Returning entry Scope %08lX partial name %wZ full name %wZ\n",
1909                       pConnection->Scope, &pConnection->RemoteName, &uniFullName));
1910
1911         ConnectCB->RemoteNameLength = pConnection->RemoteName.Length;
1912
1913         if( !bEnumerationEntry)
1914         {
1915
1916             RtlCopyMemory( ConnectCB->RemoteName,
1917                            uniFullName.Buffer,
1918                            pConnection->RemoteName.Length);
1919         }
1920         else
1921         {
1922
1923             RtlCopyMemory( ConnectCB->RemoteName,
1924                            pConnection->RemoteName.Buffer,
1925                            pConnection->RemoteName.Length);
1926         }
1927
1928         ConnectCB->LocalName = pConnection->LocalName;
1929
1930         ConnectCB->Type = pConnection->Type;
1931
1932         ConnectCB->Scope = pConnection->Scope;
1933
1934         ConnectCB->DisplayType = pConnection->DisplayType;
1935
1936         ConnectCB->Usage = pConnection->Usage;
1937
1938         ConnectCB->CommentLength = pConnection->Comment.Length;
1939
1940         ConnectCB->RemainingPathLength = uniRemainingPathLocal.Length;
1941
1942         AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1943                       AFS_TRACE_LEVEL_VERBOSE,
1944                       "AFSGetConnectionInfo Returning lengths: remote %u comment %u remaining %u\n",
1945                       ConnectCB->RemoteNameLength,
1946                       ConnectCB->CommentLength,
1947                       ConnectCB->RemainingPathLength));
1948
1949         if( ConnectCB->CommentLength > 0)
1950         {
1951
1952             ConnectCB->CommentOffset = (ULONG)(FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1953                                                              ConnectCB->RemoteNameLength);
1954
1955             RtlCopyMemory( (void *)((char *)ConnectCB + ConnectCB->CommentOffset),
1956                            pConnection->Comment.Buffer,
1957                            ConnectCB->CommentLength);
1958         }
1959
1960         if ( ConnectCB->RemainingPathLength > 0 )
1961         {
1962
1963             ConnectCB->RemainingPathOffset = (ULONG)(FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1964                                                                    ConnectCB->RemoteNameLength +
1965                                                                    ConnectCB->CommentLength);
1966
1967             RtlCopyMemory( (void *)((char *)ConnectCB + ConnectCB->RemainingPathOffset),
1968                            uniRemainingPathLocal.Buffer,
1969                            uniRemainingPathLocal.Length);
1970         }
1971
1972         *ReturnOutputBufferLength = FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1973                                                   ConnectCB->RemoteNameLength +
1974                                                   ConnectCB->CommentLength +
1975                                                   ConnectCB->RemainingPathLength;
1976
1977         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1978
1979 try_exit:
1980
1981         if ( uniRemainingPathLocal.Buffer )
1982         {
1983
1984             AFSExFreePoolWithTag( uniRemainingPathLocal.Buffer, 0);
1985         }
1986     }
1987
1988     return ntStatus;
1989 }
1990
1991 BOOLEAN
1992 AFSIsDriveMapped( IN WCHAR DriveMapping)
1993 {
1994
1995     BOOLEAN bDriveMapped = FALSE;
1996     AFSProviderConnectionCB *pConnection = NULL;
1997     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1998
1999     __Enter
2000     {
2001
2002         AFSAcquireShared( &pRDRDevExt->Specific.RDR.ProviderListLock,
2003                           TRUE);
2004
2005         pConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
2006
2007         while( pConnection != NULL)
2008         {
2009
2010             if( pConnection->LocalName != L'\0' &&
2011                 RtlUpcaseUnicodeChar( pConnection->LocalName) == RtlUpcaseUnicodeChar( DriveMapping))
2012             {
2013
2014                 bDriveMapped = TRUE;
2015
2016                 break;
2017             }
2018
2019             pConnection = pConnection->fLink;
2020         }
2021
2022         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
2023     }
2024
2025     return bDriveMapped;
2026 }