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