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