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