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