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