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