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