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