896b75fe3ba5436ab001680312a514a50d9170e9
[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         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
56                       AFS_TRACE_LEVEL_VERBOSE,
57                       "AFSAddConnection Acquiring AFSProviderListLock lock %08lX 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             AFSDbgLogMsg( 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                 AFSDbgLogMsg( 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                 AFSDbgLogMsg( 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                     AFSDbgLogMsg( 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                     AFSDbgLogMsg( 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                     AFSDbgLogMsg( 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                     AFSDbgLogMsg( 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                 AFSDbgLogMsg( 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                 AFSDbgLogMsg( 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             AFSDbgLogMsg( 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             AFSDbgLogMsg( 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         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
419                       AFS_TRACE_LEVEL_VERBOSE,
420                       "AFSCancelConnection Acquiring AFSProviderListLock lock %08lX 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             AFSDbgLogMsg( 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                 ( RtlCompareUnicodeString( &uniRemoteName,
462                                            &pConnection->RemoteName,
463                                            TRUE) == 0))
464             {
465
466                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
467                               AFS_TRACE_LEVEL_VERBOSE,
468                               "AFSCancelConnection Checking remote name %wZ to stored %wZ authentication id %I64X - %I64X\n",
469                               &uniRemoteName,
470                               &pConnection->RemoteName,
471                               ConnectCB->AuthenticationId.QuadPart,
472                               pConnection->AuthenticationId.QuadPart);
473
474                 if( ConnectCB->AuthenticationId.QuadPart == pConnection->AuthenticationId.QuadPart &&
475                     ( ConnectCB->LocalName == L'\0' ||
476                       RtlCompareUnicodeString( &uniRemoteName,
477                                                &pConnection->RemoteName,
478                                                TRUE) == 0))
479                 {
480
481                     break;
482                 }
483             }
484
485             pLastConnection = pConnection;
486
487             pConnection = pConnection->fLink;
488         }
489
490         if( pConnection == NULL)
491         {
492
493             ConnectionResult->Status = WN_NOT_CONNECTED;
494
495             *ReturnOutputBufferLength = sizeof( AFSCancelConnectionResultCB);
496
497             try_return( ntStatus);
498         }
499
500         if( pLastConnection == NULL)
501         {
502
503             pRDRDevExt->Specific.RDR.ProviderConnectionList = pConnection->fLink;
504         }
505         else
506         {
507
508             pLastConnection->fLink = pConnection->fLink;
509         }
510
511         if( pConnection->Comment.Buffer != NULL)
512         {
513
514             AFSExFreePoolWithTag( pConnection->Comment.Buffer, 0);
515         }
516
517         ConnectionResult->LocalName = pConnection->LocalName;
518
519         AFSExFreePoolWithTag( pConnection, AFS_PROVIDER_CB);
520
521         ConnectionResult->Status = WN_SUCCESS;
522
523         *ReturnOutputBufferLength = sizeof( AFSCancelConnectionResultCB);
524
525 try_exit:
526
527         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
528     }
529
530     return ntStatus;
531 }
532
533 NTSTATUS
534 AFSGetConnection( IN AFSNetworkProviderConnectionCB *ConnectCB,
535                   IN OUT WCHAR *RemoteName,
536                   IN ULONG RemoteNameBufferLength,
537                   IN OUT ULONG_PTR *ReturnOutputBufferLength)
538 {
539
540     NTSTATUS ntStatus = STATUS_SUCCESS;
541     AFSProviderConnectionCB *pConnection = NULL;
542     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
543
544     __Enter
545     {
546
547         if( ConnectCB->LocalName != L'\0')
548         {
549
550             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
551                           AFS_TRACE_LEVEL_VERBOSE,
552                           "AFSGetConnection Local %C authentication id %I64X\n",
553                           ConnectCB->LocalName,
554                           ConnectCB->AuthenticationId.QuadPart);
555         }
556         else
557         {
558
559             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
560                           AFS_TRACE_LEVEL_VERBOSE,
561                           "AFSGetConnection Local (NULL) authentication id %I64X\n",
562                           ConnectCB->AuthenticationId.QuadPart);
563         }
564
565         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
566                       AFS_TRACE_LEVEL_VERBOSE,
567                       "AFSGetConnection Acquiring AFSProviderListLock lock %08lX SHARED %08lX\n",
568                       &pRDRDevExt->Specific.RDR.ProviderListLock,
569                       PsGetCurrentThread());
570
571         if( ConnectCB->AuthenticationId.QuadPart == 0)
572         {
573
574             ConnectCB->AuthenticationId = AFSGetAuthenticationId();
575
576             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
577                           AFS_TRACE_LEVEL_VERBOSE,
578                           "AFSGetConnection Retrieved authentication id %I64X\n",
579                           ConnectCB->AuthenticationId.QuadPart);
580         }
581
582         AFSAcquireShared( &pRDRDevExt->Specific.RDR.ProviderListLock,
583                           TRUE);
584
585         //
586         // Look for the connection
587         //
588
589         pConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
590
591         while( pConnection != NULL)
592         {
593
594             if( pConnection->LocalName != L'\0')
595             {
596
597                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
598                               AFS_TRACE_LEVEL_VERBOSE,
599                               "AFSGetConnection Comparing passed in %C to %C authentication id %I64X - %I64X\n",
600                               ConnectCB->LocalName,
601                               pConnection->LocalName,
602                               ConnectCB->AuthenticationId.QuadPart,
603                               pConnection->AuthenticationId.QuadPart);
604             }
605             else
606             {
607
608                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
609                               AFS_TRACE_LEVEL_VERBOSE,
610                               "AFSGetConnection Comparing passed in %C to (NULL) authentication id %I64X - %I64X\n",
611                               ConnectCB->LocalName,
612                               ConnectCB->AuthenticationId.QuadPart,
613                               pConnection->AuthenticationId.QuadPart);
614             }
615
616             if( pConnection->LocalName == ConnectCB->LocalName &&
617                 pConnection->AuthenticationId.QuadPart == ConnectCB->AuthenticationId.QuadPart)
618             {
619
620                 break;
621             }
622
623             pConnection = pConnection->fLink;
624         }
625
626         if( pConnection == NULL)
627         {
628
629             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
630                           AFS_TRACE_LEVEL_VERBOSE,
631                           "AFSGetConnection INVALID_PARAMETER\n");
632
633             try_return( ntStatus = STATUS_INVALID_PARAMETER);
634         }
635
636         if( RemoteNameBufferLength < pConnection->RemoteName.Length)
637         {
638
639             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
640                           AFS_TRACE_LEVEL_VERBOSE,
641                           "AFSGetConnection INSUFFICIENT_RESOURCES\n");
642
643             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
644         }
645
646         RtlCopyMemory( RemoteName,
647                        pConnection->RemoteName.Buffer,
648                        pConnection->RemoteName.Length);
649
650         *ReturnOutputBufferLength = pConnection->RemoteName.Length;
651
652 try_exit:
653
654         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
655     }
656
657     return ntStatus;
658 }
659
660 NTSTATUS
661 AFSListConnections( IN OUT AFSNetworkProviderConnectionCB *ConnectCB,
662                     IN ULONG ConnectionBufferLength,
663                     IN OUT ULONG_PTR *ReturnOutputBufferLength)
664 {
665
666     NTSTATUS ntStatus = STATUS_SUCCESS;
667     AFSProviderConnectionCB *pConnection = NULL, *pRootConnection = NULL;
668     ULONG ulCopiedLength = 0, ulRemainingLength = ConnectionBufferLength;
669     ULONG ulScope, ulType;
670     UNICODE_STRING uniRemoteName, uniServerName, uniShareName, uniRemainingPath;
671     BOOLEAN bGlobalEnumeration = FALSE;
672     ULONG       ulIndex = 0;
673     LARGE_INTEGER liAuthenticationID = {0,0};
674     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
675
676     __Enter
677     {
678
679         //
680         // Save off some data before moving on
681         //
682
683         ulScope = ConnectCB->Scope;
684
685         ulType = ConnectCB->Type;
686
687         if( ConnectCB->AuthenticationId.QuadPart == 0)
688         {
689
690             ConnectCB->AuthenticationId = AFSGetAuthenticationId();
691
692             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
693                           AFS_TRACE_LEVEL_VERBOSE,
694                           "AFSListConnections Retrieved authentication id %I64X\n",
695                           ConnectCB->AuthenticationId.QuadPart);
696         }
697
698         liAuthenticationID.QuadPart = ConnectCB->AuthenticationId.QuadPart;
699
700         uniRemoteName.Length = 0;
701         uniRemoteName.MaximumLength = 0;
702         uniRemoteName.Buffer = NULL;
703
704         uniServerName.Length = 0;
705         uniServerName.MaximumLength = 0;
706         uniServerName.Buffer = NULL;
707
708         uniShareName.Length = 0;
709         uniShareName.MaximumLength = 0;
710         uniShareName.Buffer = NULL;
711
712         if( ConnectCB->RemoteNameLength > 0)
713         {
714
715             uniRemoteName.Length = (USHORT)ConnectCB->RemoteNameLength;
716             uniRemoteName.MaximumLength = uniRemoteName.Length + sizeof( WCHAR);
717
718             uniRemoteName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
719                                                                       uniRemoteName.MaximumLength,
720                                                                       AFS_NETWORK_PROVIDER_1_TAG);
721
722             if( uniRemoteName.Buffer == NULL)
723             {
724
725                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
726             }
727
728             RtlCopyMemory( uniRemoteName.Buffer,
729                            ConnectCB->RemoteName,
730                            uniRemoteName.Length);
731
732             if( uniRemoteName.Buffer[ 0] == L'\\' &&
733                 uniRemoteName.Buffer[ 1] == L'\\')
734             {
735
736                 uniRemoteName.Buffer = &uniRemoteName.Buffer[ 1];
737
738                 uniRemoteName.Length -= sizeof( WCHAR);
739             }
740
741             if( uniRemoteName.Buffer[ (uniRemoteName.Length/sizeof( WCHAR)) - 1] == L'\\')
742             {
743
744                 uniRemoteName.Length -= sizeof( WCHAR);
745             }
746
747             FsRtlDissectName( uniRemoteName,
748                               &uniServerName,
749                               &uniRemainingPath);
750
751             uniRemoteName = uniRemainingPath;
752
753             if( uniRemoteName.Length > 0)
754             {
755
756                 FsRtlDissectName( uniRemoteName,
757                                   &uniShareName,
758                                   &uniRemainingPath);
759             }
760
761             //
762             // If this is an enumeration of the global share name then
763             // adjust it to be the server name itself
764             //
765
766             if( uniShareName.Length == 0 ||
767                 RtlCompareUnicodeString( &uniShareName,
768                                          &AFSGlobalRootName,
769                                          TRUE) == 0)
770             {
771
772                 bGlobalEnumeration = TRUE;
773             }
774         }
775
776         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
777                       AFS_TRACE_LEVEL_VERBOSE,
778                       "AFSListConnections Acquiring AFSProviderListLock lock %08lX SHARED %08lX\n",
779                       &pRDRDevExt->Specific.RDR.ProviderListLock,
780                       PsGetCurrentThread());
781
782         AFSAcquireShared( &pRDRDevExt->Specific.RDR.ProviderListLock,
783                           TRUE);
784
785         //
786         // If this is a globalnet enumeration with no name then enumerate the server list
787         //
788
789         if( ulScope == RESOURCE_GLOBALNET)
790         {
791
792             if( uniServerName.Buffer == NULL)
793             {
794
795                 pConnection = pRDRDevExt->Specific.RDR.ProviderEnumerationList;
796             }
797             else
798             {
799
800                 //
801                 // Go locate the root entry for the name passed in
802                 //
803
804                 if( bGlobalEnumeration)
805                 {
806
807                     if( pRDRDevExt->Specific.RDR.ProviderEnumerationList == NULL)
808                     {
809
810                         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
811
812                         try_return( ntStatus);
813                     }
814
815                     pConnection = pRDRDevExt->Specific.RDR.ProviderEnumerationList->EnumerationList;
816                 }
817                 else
818                 {
819
820                     pRootConnection = AFSLocateEnumRootEntry( &uniShareName);
821
822                     if( pRootConnection == NULL)
823                     {
824
825                         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
826
827                         try_return( ntStatus);
828                     }
829
830                     //
831                     // Need to handle these enumerations from the directory listing
832                     //
833
834                     ntStatus = AFSEnumerateConnection( ConnectCB,
835                                                        pRootConnection,
836                                                        ConnectionBufferLength,
837                                                        &ulCopiedLength);
838                 }
839             }
840         }
841         else
842         {
843
844             pConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
845         }
846
847         ulIndex = ConnectCB->CurrentIndex;
848
849         while( pConnection != NULL)
850         {
851
852             if( bGlobalEnumeration &&
853                 BooleanFlagOn( pConnection->Flags, AFS_CONNECTION_FLAG_GLOBAL_SHARE))
854             {
855
856                 pConnection = pConnection->fLink;
857
858                 continue;
859             }
860
861             if( ulScope != RESOURCE_GLOBALNET &&
862                 !BooleanFlagOn( pConnection->Usage, RESOURCEUSAGE_ATTACHED))
863             {
864
865                 pConnection = pConnection->fLink;
866
867                 continue;
868             }
869
870             if( pConnection->LocalName != L'\0')
871             {
872
873                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
874                               AFS_TRACE_LEVEL_VERBOSE,
875                               "AFSListConnections Processing entry %wZ %C authentication id %I64X - %I64X Scope %08lX\n",
876                               &pConnection->RemoteName,
877                               pConnection->LocalName,
878                               liAuthenticationID.QuadPart,
879                               pConnection->AuthenticationId.QuadPart,
880                               pConnection->Scope);
881             }
882             else
883             {
884
885                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
886                               AFS_TRACE_LEVEL_VERBOSE,
887                               "AFSListConnections Processing entry %wZ NULL LocalName authentication id %I64X - %I64X Scope %08lX\n",
888                               &pConnection->RemoteName,
889                               liAuthenticationID.QuadPart,
890                               pConnection->AuthenticationId.QuadPart,
891                               pConnection->Scope);
892             }
893
894             if( ulScope != RESOURCE_GLOBALNET &&
895                 pConnection->AuthenticationId.QuadPart != liAuthenticationID.QuadPart)
896             {
897
898                 pConnection = pConnection->fLink;
899
900                 continue;
901             }
902
903             if( ulIndex > 0)
904             {
905
906                 ulIndex--;
907
908                 pConnection = pConnection->fLink;
909
910                 continue;
911             }
912
913             if( ulRemainingLength < (ULONG)FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
914                                                          pConnection->RemoteName.Length +
915                                                          pConnection->Comment.Length)
916             {
917
918                 break;
919             }
920
921             ConnectCB->RemoteNameLength = pConnection->RemoteName.Length;
922
923             RtlCopyMemory( ConnectCB->RemoteName,
924                            pConnection->RemoteName.Buffer,
925                            pConnection->RemoteName.Length);
926
927             ConnectCB->LocalName = pConnection->LocalName;
928
929             ConnectCB->Type = pConnection->Type;
930
931             ConnectCB->Scope = pConnection->Scope;
932
933             if( !bGlobalEnumeration)
934             {
935
936                 ConnectCB->Scope = RESOURCE_CONNECTED;
937             }
938
939             ConnectCB->DisplayType = pConnection->DisplayType;
940
941             ConnectCB->Usage = pConnection->Usage;
942
943             ConnectCB->CommentLength = pConnection->Comment.Length;
944
945             if( pConnection->Comment.Length > 0)
946             {
947
948                 ConnectCB->CommentOffset = (ULONG)(FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
949                                                                         ConnectCB->RemoteNameLength);
950
951                 RtlCopyMemory( (void *)((char *)ConnectCB + ConnectCB->CommentOffset),
952                                pConnection->Comment.Buffer,
953                                ConnectCB->CommentLength);
954             }
955
956             ulCopiedLength += FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
957                                                     ConnectCB->RemoteNameLength +
958                                                     ConnectCB->CommentLength;
959
960             ulRemainingLength -= FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
961                                                     ConnectCB->RemoteNameLength +
962                                                     ConnectCB->CommentLength;
963
964             ConnectCB = (AFSNetworkProviderConnectionCB *)((char *)ConnectCB +
965                                                             FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
966                                                             ConnectCB->RemoteNameLength +
967                                                             ConnectCB->CommentLength);
968
969             pConnection = pConnection->fLink;
970         }
971
972         if( NT_SUCCESS( ntStatus))
973         {
974
975             *ReturnOutputBufferLength = ulCopiedLength;
976         }
977
978         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
979
980 try_exit:
981
982         if( uniRemoteName.Buffer != NULL)
983         {
984
985             AFSExFreePoolWithTag( uniRemoteName.Buffer, 0);
986         }
987     }
988
989     return ntStatus;
990 }
991
992 void
993 AFSInitializeConnectionInfo( IN AFSProviderConnectionCB *Connection,
994                              IN ULONG DisplayType)
995 {
996
997     NTSTATUS ntStatus = STATUS_SUCCESS;
998     UNICODE_STRING uniName, uniComponentName, uniRemainingName;
999
1000     __Enter
1001     {
1002
1003         uniName = Connection->RemoteName;
1004
1005         //
1006         // Strip of the double leading slash if there is one
1007         //
1008
1009         if( uniName.Buffer[ 0] == L'\\' &&
1010             uniName.Buffer[ 1] == L'\\')
1011         {
1012
1013             uniName.Buffer = &uniName.Buffer[ 1];
1014
1015             uniName.Length -= sizeof( WCHAR);
1016         }
1017
1018
1019         FsRtlDissectName( uniName,
1020                           &uniComponentName,
1021                           &uniRemainingName);
1022
1023         //
1024         // Initialize the information for the connection
1025         // First, if this is the server only then mark it accordingly
1026         //
1027
1028         if( uniRemainingName.Length == 0 ||
1029             DisplayType == RESOURCEDISPLAYTYPE_SERVER)
1030         {
1031
1032             Connection->Type = RESOURCETYPE_DISK;
1033
1034             Connection->Scope = 0;
1035
1036             Connection->DisplayType = RESOURCEDISPLAYTYPE_SERVER;
1037
1038             Connection->Usage = RESOURCEUSAGE_CONTAINER;
1039
1040             Connection->Comment.Length = 20;
1041             Connection->Comment.MaximumLength = 22;
1042
1043             Connection->Comment.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1044                                                                             Connection->Comment.MaximumLength,
1045                                                                             AFS_NETWORK_PROVIDER_2_TAG);
1046
1047             if( Connection->Comment.Buffer != NULL)
1048             {
1049
1050                 RtlZeroMemory( Connection->Comment.Buffer,
1051                                Connection->Comment.MaximumLength);
1052
1053                 RtlCopyMemory( Connection->Comment.Buffer,
1054                                L"AFS Root",
1055                                16);
1056             }
1057             else
1058             {
1059
1060                 Connection->Comment.Length = 0;
1061                 Connection->Comment.MaximumLength = 0;
1062             }
1063
1064             try_return( ntStatus);
1065         }
1066
1067         uniName = uniRemainingName;
1068
1069         FsRtlDissectName( uniName,
1070                           &uniComponentName,
1071                           &uniRemainingName);
1072
1073         if( uniRemainingName.Length == 0 ||
1074             uniRemainingName.Buffer == NULL ||
1075             DisplayType == RESOURCEDISPLAYTYPE_SHARE)
1076         {
1077
1078             Connection->Type = RESOURCETYPE_DISK;
1079
1080             Connection->DisplayType = RESOURCEDISPLAYTYPE_SHARE;
1081
1082             Connection->Usage = RESOURCEUSAGE_CONNECTABLE;
1083
1084             if( Connection->LocalName != L'\0')
1085             {
1086
1087                 Connection->Usage |= RESOURCEUSAGE_ATTACHED;
1088
1089                 Connection->Scope = RESOURCE_CONNECTED;
1090             }
1091             else
1092             {
1093
1094                 Connection->Usage |= RESOURCEUSAGE_NOLOCALDEVICE;
1095
1096                 Connection->Scope = RESOURCE_GLOBALNET;
1097             }
1098
1099             Connection->Comment.Length = 18;
1100             Connection->Comment.MaximumLength = 20;
1101
1102             Connection->Comment.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1103                                                                             Connection->Comment.MaximumLength,
1104                                                                             AFS_NETWORK_PROVIDER_3_TAG);
1105
1106             if( Connection->Comment.Buffer != NULL)
1107             {
1108
1109                 RtlZeroMemory( Connection->Comment.Buffer,
1110                                Connection->Comment.MaximumLength);
1111
1112                 RtlCopyMemory( Connection->Comment.Buffer,
1113                                L"AFS Share",
1114                                18);
1115             }
1116             else
1117             {
1118
1119                 Connection->Comment.Length = 0;
1120                 Connection->Comment.MaximumLength = 0;
1121             }
1122
1123             try_return( ntStatus);
1124         }
1125
1126         //
1127         // This is a sub directory within a share
1128         //
1129
1130         Connection->Type = RESOURCETYPE_DISK;
1131
1132         Connection->DisplayType = RESOURCEDISPLAYTYPE_DIRECTORY;
1133
1134         Connection->Usage = RESOURCEUSAGE_CONNECTABLE;
1135
1136         if( Connection->LocalName != L'\0')
1137         {
1138
1139             Connection->Usage |= RESOURCEUSAGE_ATTACHED;
1140         }
1141         else
1142         {
1143
1144             Connection->Usage |= RESOURCEUSAGE_NOLOCALDEVICE;
1145         }
1146
1147         Connection->Scope = RESOURCE_CONNECTED;
1148
1149         Connection->Comment.Length = 26;
1150         Connection->Comment.MaximumLength = 28;
1151
1152         Connection->Comment.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1153                                                                         Connection->Comment.MaximumLength,
1154                                                                         AFS_NETWORK_PROVIDER_4_TAG);
1155
1156         if( Connection->Comment.Buffer != NULL)
1157         {
1158
1159             RtlZeroMemory( Connection->Comment.Buffer,
1160                            Connection->Comment.MaximumLength);
1161
1162             RtlCopyMemory( Connection->Comment.Buffer,
1163                            L"AFS Directory",
1164                            26);
1165         }
1166         else
1167         {
1168
1169             Connection->Comment.Length = 0;
1170             Connection->Comment.MaximumLength = 0;
1171         }
1172
1173 try_exit:
1174
1175         NOTHING;
1176     }
1177
1178     return;
1179 }
1180
1181 AFSProviderConnectionCB *
1182 AFSLocateEnumRootEntry( IN UNICODE_STRING *RemoteName)
1183 {
1184
1185     AFSProviderConnectionCB *pConnection = NULL;
1186     UNICODE_STRING uniRemoteName = *RemoteName;
1187     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1188
1189     __Enter
1190     {
1191
1192         if( pRDRDevExt->Specific.RDR.ProviderEnumerationList == NULL)
1193         {
1194
1195             try_return( pConnection);
1196         }
1197
1198         pConnection = pRDRDevExt->Specific.RDR.ProviderEnumerationList->EnumerationList;
1199
1200         while( pConnection != NULL)
1201         {
1202
1203             if( RtlCompareUnicodeString( &uniRemoteName,
1204                                          &pConnection->ComponentName,
1205                                          TRUE) == 0)
1206             {
1207
1208                 break;
1209             }
1210
1211             pConnection = pConnection->fLink;
1212         }
1213
1214 try_exit:
1215
1216         NOTHING;
1217     }
1218
1219     return pConnection;
1220 }
1221
1222 NTSTATUS
1223 AFSEnumerateConnection( IN OUT AFSNetworkProviderConnectionCB *ConnectCB,
1224                         IN AFSProviderConnectionCB *RootConnection,
1225                         IN ULONG BufferLength,
1226                         OUT PULONG CopiedLength)
1227 {
1228
1229     NTSTATUS ntStatus = STATUS_SUCCESS;
1230     ULONG ulCRC = 0, ulCopiedLength = 0;
1231     AFSDirectoryCB *pShareDirEntry = NULL;
1232     AFSDirectoryCB *pDirEntry = NULL, *pTargetDirEntry = NULL;
1233     ULONG ulIndex = 0;
1234     LONG lCount;
1235
1236     __Enter
1237     {
1238
1239         if( AFSGlobalRoot == NULL)
1240         {
1241
1242             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1243                           AFS_TRACE_LEVEL_ERROR,
1244                           "AFSEnumerateConnection Global root not yet initialized\n");
1245
1246             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1247         }
1248
1249         ulCRC = AFSGenerateCRC( &RootConnection->ComponentName,
1250                                 FALSE);
1251
1252         //
1253         // Grab our tree lock shared
1254         //
1255
1256         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1257                       AFS_TRACE_LEVEL_VERBOSE,
1258                       "AFSEnumerateConnection Acquiring GlobalRoot DirectoryNodeHdr.TreeLock lock %08lX SHARED %08lX\n",
1259                       AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
1260                       PsGetCurrentThread());
1261
1262         AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
1263                           TRUE);
1264
1265         //
1266         // Locate the dir entry for this node
1267         //
1268
1269         ntStatus = AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1270                                                    ulCRC,
1271                                                    &pShareDirEntry);
1272
1273         if( pShareDirEntry == NULL ||
1274             !NT_SUCCESS( ntStatus))
1275         {
1276
1277             //
1278             // Perform a case insensitive search
1279             //
1280
1281             ulCRC = AFSGenerateCRC( &RootConnection->ComponentName,
1282                                     TRUE);
1283
1284             ntStatus = AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1285                                                          ulCRC,
1286                                                          &pShareDirEntry);
1287
1288             if( pShareDirEntry == NULL ||
1289                 !NT_SUCCESS( ntStatus))
1290             {
1291
1292                 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
1293
1294                 try_return( ntStatus);
1295             }
1296         }
1297
1298         lCount = InterlockedIncrement( &pShareDirEntry->DirOpenReferenceCount);
1299
1300         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1301                       AFS_TRACE_LEVEL_VERBOSE,
1302                       "AFSEnumerateConnection1 Increment count on %wZ DE %p Ccb %p Cnt %d\n",
1303                       &pShareDirEntry->NameInformation.FileName,
1304                       pShareDirEntry,
1305                       NULL,
1306                       lCount);
1307
1308         AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
1309
1310         //
1311         // Setup the request to evaluate the entry
1312         //
1313
1314         ntStatus = AFSEvaluateRootEntry( pShareDirEntry,
1315                                          &pTargetDirEntry);
1316
1317         if( !NT_SUCCESS( ntStatus))
1318         {
1319
1320             try_return( ntStatus);
1321         }
1322
1323         AFSAcquireShared( pTargetDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1324                           TRUE);
1325
1326         //
1327         // Enumerate the content
1328         //
1329
1330         pDirEntry = pTargetDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
1331
1332         ulIndex = ConnectCB->CurrentIndex;
1333
1334         while( pDirEntry != NULL)
1335         {
1336
1337             if( ulIndex > 0)
1338             {
1339
1340                 ulIndex--;
1341
1342                 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
1343
1344                 continue;
1345             }
1346
1347             if( BufferLength < (ULONG)FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1348                                                                pDirEntry->NameInformation.FileName.Length)
1349             {
1350
1351                 break;
1352             }
1353
1354             ConnectCB->LocalName = L'\0';
1355
1356             ConnectCB->RemoteNameLength = pDirEntry->NameInformation.FileName.Length;
1357
1358             RtlCopyMemory( ConnectCB->RemoteName,
1359                            pDirEntry->NameInformation.FileName.Buffer,
1360                            pDirEntry->NameInformation.FileName.Length);
1361
1362             ConnectCB->Type = RESOURCETYPE_DISK;
1363
1364             ConnectCB->Scope = RESOURCE_CONNECTED;
1365
1366             if( BooleanFlagOn( pDirEntry->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
1367             {
1368
1369                 ConnectCB->DisplayType = RESOURCEDISPLAYTYPE_DIRECTORY;
1370             }
1371             else
1372             {
1373
1374                 ConnectCB->DisplayType = RESOURCEDISPLAYTYPE_FILE;
1375             }
1376
1377             ConnectCB->Usage = 0;
1378
1379             ConnectCB->CommentLength = 0;
1380
1381             ulCopiedLength += FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1382                                                     pDirEntry->NameInformation.FileName.Length;
1383
1384             BufferLength -= FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1385                                                     pDirEntry->NameInformation.FileName.Length;
1386
1387             ConnectCB = (AFSNetworkProviderConnectionCB *)((char *)ConnectCB +
1388                                                             FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1389                                                             ConnectCB->RemoteNameLength);
1390
1391             pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
1392         }
1393
1394         lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount);
1395
1396         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1397                       AFS_TRACE_LEVEL_VERBOSE,
1398                       "AFSEnumerateConnection Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1399                       &pTargetDirEntry->NameInformation.FileName,
1400                       pTargetDirEntry,
1401                       NULL,
1402                       lCount);
1403
1404         ASSERT( lCount >= 0);
1405
1406         *CopiedLength = ulCopiedLength;
1407
1408         AFSReleaseResource( pTargetDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1409
1410 try_exit:
1411
1412         if( pShareDirEntry != NULL)
1413         {
1414             lCount = InterlockedDecrement( &pShareDirEntry->DirOpenReferenceCount);
1415
1416             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1417                           AFS_TRACE_LEVEL_VERBOSE,
1418                           "AFSEnumerateConnection1 Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1419                           &pShareDirEntry->NameInformation.FileName,
1420                           pShareDirEntry,
1421                           NULL,
1422                           lCount);
1423
1424             ASSERT( lCount >= 0);
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             AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_3_TAG);
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             AFSExFreePoolWithTag( uniFullName.Buffer, 0);
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             AFSExFreePoolWithTag( uniRemainingPathLocal.Buffer, 0);
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 }