Windows: DirOpenReferenceCount reorganizing completed
[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 %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             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 %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             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 %p 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 %p 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 %p 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         // On success, pTargetDirEntry has the DirOpenReferenceCount held
1313         //
1314
1315         ntStatus = AFSEvaluateRootEntry( pShareDirEntry,
1316                                          &pTargetDirEntry);
1317
1318         if( !NT_SUCCESS( ntStatus))
1319         {
1320
1321             try_return( ntStatus);
1322         }
1323
1324         AFSAcquireShared( pTargetDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1325                           TRUE);
1326
1327         //
1328         // Enumerate the content
1329         //
1330
1331         pDirEntry = pTargetDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
1332
1333         ulIndex = ConnectCB->CurrentIndex;
1334
1335         while( pDirEntry != NULL)
1336         {
1337
1338             if( ulIndex > 0)
1339             {
1340
1341                 ulIndex--;
1342
1343                 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
1344
1345                 continue;
1346             }
1347
1348             if( BufferLength < (ULONG)FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1349                                                                pDirEntry->NameInformation.FileName.Length)
1350             {
1351
1352                 break;
1353             }
1354
1355             ConnectCB->LocalName = L'\0';
1356
1357             ConnectCB->RemoteNameLength = pDirEntry->NameInformation.FileName.Length;
1358
1359             RtlCopyMemory( ConnectCB->RemoteName,
1360                            pDirEntry->NameInformation.FileName.Buffer,
1361                            pDirEntry->NameInformation.FileName.Length);
1362
1363             ConnectCB->Type = RESOURCETYPE_DISK;
1364
1365             ConnectCB->Scope = RESOURCE_CONNECTED;
1366
1367             if( BooleanFlagOn( pDirEntry->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
1368             {
1369
1370                 ConnectCB->DisplayType = RESOURCEDISPLAYTYPE_DIRECTORY;
1371             }
1372             else
1373             {
1374
1375                 ConnectCB->DisplayType = RESOURCEDISPLAYTYPE_FILE;
1376             }
1377
1378             ConnectCB->Usage = 0;
1379
1380             ConnectCB->CommentLength = 0;
1381
1382             ulCopiedLength += FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1383                                                     pDirEntry->NameInformation.FileName.Length;
1384
1385             BufferLength -= FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1386                                                     pDirEntry->NameInformation.FileName.Length;
1387
1388             ConnectCB = (AFSNetworkProviderConnectionCB *)((char *)ConnectCB +
1389                                                             FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1390                                                             ConnectCB->RemoteNameLength);
1391
1392             pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
1393         }
1394
1395         //
1396         // Release the DirOpenReferenceCount obtained from AFSEvaluateRootEntry
1397         //
1398
1399         lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount);
1400
1401         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1402                       AFS_TRACE_LEVEL_VERBOSE,
1403                       "AFSEnumerateConnection Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1404                       &pTargetDirEntry->NameInformation.FileName,
1405                       pTargetDirEntry,
1406                       NULL,
1407                       lCount);
1408
1409         ASSERT( lCount >= 0);
1410
1411         *CopiedLength = ulCopiedLength;
1412
1413         AFSReleaseResource( pTargetDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1414
1415 try_exit:
1416
1417         if( pShareDirEntry != NULL)
1418         {
1419             lCount = InterlockedDecrement( &pShareDirEntry->DirOpenReferenceCount);
1420
1421             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1422                           AFS_TRACE_LEVEL_VERBOSE,
1423                           "AFSEnumerateConnection1 Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1424                           &pShareDirEntry->NameInformation.FileName,
1425                           pShareDirEntry,
1426                           NULL,
1427                           lCount);
1428
1429             ASSERT( lCount >= 0);
1430         }
1431     }
1432
1433     return ntStatus;
1434 }
1435
1436 NTSTATUS
1437 AFSGetConnectionInfo( IN AFSNetworkProviderConnectionCB *ConnectCB,
1438                       IN ULONG BufferLength,
1439                       IN OUT ULONG_PTR *ReturnOutputBufferLength)
1440 {
1441
1442     NTSTATUS ntStatus = STATUS_SUCCESS;
1443     AFSProviderConnectionCB *pConnection = NULL, *pBestMatch = NULL;
1444     UNICODE_STRING uniRemoteName, uniServerName, uniShareName, uniRemainingPath, uniFullName, uniRemainingPathLocal;
1445     USHORT usNameLen = 0, usMaxNameLen = 0;
1446     BOOLEAN bEnumerationEntry = FALSE;
1447     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1448
1449     __Enter
1450     {
1451
1452         uniServerName.Length = 0;
1453         uniServerName.MaximumLength = 0;
1454         uniServerName.Buffer = NULL;
1455
1456         uniShareName.Length = 0;
1457         uniShareName.MaximumLength = 0;
1458         uniShareName.Buffer = NULL;
1459
1460         uniRemainingPathLocal.Length = 0;
1461         uniRemainingPathLocal.MaximumLength = 0;
1462         uniRemainingPathLocal.Buffer = NULL;
1463
1464         uniRemoteName.Length = (USHORT)ConnectCB->RemoteNameLength;
1465         uniRemoteName.MaximumLength = uniRemoteName.Length + sizeof( WCHAR);
1466         uniRemoteName.Buffer = (WCHAR *)ConnectCB->RemoteName;
1467
1468         if( ConnectCB->LocalName != L'\0')
1469         {
1470
1471             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1472                           AFS_TRACE_LEVEL_VERBOSE,
1473                           "AFSGetConnectionInfo remote name %wZ Local %C authentication id %I64X\n",
1474                           &uniRemoteName,
1475                           ConnectCB->LocalName,
1476                           ConnectCB->AuthenticationId.QuadPart);
1477         }
1478         else
1479         {
1480
1481             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1482                           AFS_TRACE_LEVEL_VERBOSE,
1483                           "AFSGetConnectionInfo remote name %wZ Local (NULL) authentication id %I64X\n",
1484                           &uniRemoteName,
1485                           ConnectCB->AuthenticationId.QuadPart);
1486         }
1487
1488         if( AFSGlobalRoot == NULL)
1489         {
1490
1491             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1492                           AFS_TRACE_LEVEL_ERROR,
1493                           "AFSGetConnectionInfo Global root not yet initialized\n");
1494
1495             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1496         }
1497
1498         uniFullName = uniRemoteName;
1499
1500         if( uniRemoteName.Buffer[ 0] == L'\\' &&
1501             uniRemoteName.Buffer[ 1] == L'\\')
1502         {
1503
1504             uniRemoteName.Buffer = &uniRemoteName.Buffer[ 1];
1505
1506             uniRemoteName.Length -= sizeof( WCHAR);
1507         }
1508
1509         if( uniRemoteName.Buffer[ (uniRemoteName.Length/sizeof( WCHAR)) - 1] == L'\\')
1510         {
1511
1512             uniRemoteName.Length -= sizeof( WCHAR);
1513
1514             uniFullName.Length -= sizeof( WCHAR);
1515         }
1516
1517         AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1518                       AFS_TRACE_LEVEL_VERBOSE,
1519                       "AFSGetConnectionInfo Processing name %wZ\n", &uniFullName);
1520
1521         FsRtlDissectName( uniRemoteName,
1522                           &uniServerName,
1523                           &uniRemainingPath);
1524
1525         uniRemoteName = uniRemainingPath;
1526
1527         if( uniRemoteName.Length > 0)
1528         {
1529
1530             FsRtlDissectName( uniRemoteName,
1531                               &uniShareName,
1532                               &uniRemainingPath);
1533         }
1534
1535         if( RtlCompareUnicodeString( &uniServerName,
1536                                      &AFSServerName,
1537                                      TRUE) != 0)
1538         {
1539
1540             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1541         }
1542
1543         if ( uniRemainingPath.Length > 0 )
1544         {
1545
1546             //
1547             // Add back in the leading \ since it was stripped off above
1548             //
1549
1550             uniRemainingPath.Length += sizeof( WCHAR);
1551             if( uniRemainingPath.Length > uniRemainingPath.MaximumLength)
1552             {
1553                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
1554             }
1555
1556             uniRemainingPath.Buffer--;
1557
1558             uniRemainingPathLocal.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1559                                                                               uniRemainingPath.Length,
1560                                                                               AFS_NETWORK_PROVIDER_5_TAG);
1561
1562             if( uniRemainingPathLocal.Buffer == NULL)
1563             {
1564
1565                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1566                               AFS_TRACE_LEVEL_VERBOSE,
1567                               "AFSGetConnectionInfo INSUFFICIENT_RESOURCES\n");
1568
1569                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1570             }
1571
1572             uniRemainingPathLocal.MaximumLength = uniRemainingPath.Length;
1573             uniRemainingPathLocal.Length = uniRemainingPath.Length;
1574
1575             RtlCopyMemory( uniRemainingPathLocal.Buffer,
1576                            uniRemainingPath.Buffer,
1577                            uniRemainingPath.Length);
1578         }
1579
1580         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1581                       AFS_TRACE_LEVEL_VERBOSE,
1582                       "AFSGetConnectionInfo Acquiring AFSProviderListLock lock %p SHARED %08lX\n",
1583                       &pRDRDevExt->Specific.RDR.ProviderListLock,
1584                       PsGetCurrentThread());
1585
1586         AFSAcquireShared( &pRDRDevExt->Specific.RDR.ProviderListLock,
1587                           TRUE);
1588
1589         //
1590         // If this is the server then return information about the
1591         // server entry
1592         //
1593
1594         if( uniShareName.Length == 0 &&
1595             RtlCompareUnicodeString( &uniServerName,
1596                                      &AFSServerName,
1597                                      TRUE) == 0)
1598         {
1599
1600             pConnection = pRDRDevExt->Specific.RDR.ProviderEnumerationList;
1601         }
1602         else
1603         {
1604
1605             //
1606             // See if we can locate it on our connection list
1607             //
1608
1609             pConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
1610
1611             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1612                           AFS_TRACE_LEVEL_VERBOSE,
1613                           "AFSGetConnectionInfo Searching for full name %wZ\n", &uniFullName);
1614
1615             while( pConnection != NULL)
1616             {
1617
1618                 if( usMaxNameLen < pConnection->RemoteName.Length &&
1619                     pConnection->RemoteName.Length <= uniFullName.Length)
1620                 {
1621
1622                     usNameLen = uniFullName.Length;
1623
1624                     uniFullName.Length = pConnection->RemoteName.Length;
1625
1626                     if( pConnection->AuthenticationId.QuadPart == ConnectCB->AuthenticationId.QuadPart &&
1627                         RtlCompareUnicodeString( &uniFullName,
1628                                                  &pConnection->RemoteName,
1629                                                  TRUE) == 0)
1630                     {
1631
1632                         usMaxNameLen = pConnection->RemoteName.Length;
1633
1634                         pBestMatch = pConnection;
1635
1636                         AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1637                                       AFS_TRACE_LEVEL_VERBOSE,
1638                                       "AFSGetConnectionInfo Found match for %wZ\n", &pConnection->RemoteName);
1639                     }
1640
1641                     uniFullName.Length = usNameLen;
1642                 }
1643
1644                 pConnection = pConnection->fLink;
1645             }
1646
1647             pConnection = pBestMatch;
1648
1649             if( pConnection != NULL)
1650             {
1651
1652                 bEnumerationEntry = TRUE;
1653
1654                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1655                               AFS_TRACE_LEVEL_VERBOSE,
1656                               "AFSGetConnectionInfo Using best match for %wZ\n", &pConnection->RemoteName);
1657             }
1658
1659             if( pConnection == NULL)
1660             {
1661
1662                 //
1663                 // Locate the entry for the share
1664                 //
1665
1666                 pConnection = AFSLocateEnumRootEntry( &uniShareName);
1667             }
1668         }
1669
1670         if( pConnection == NULL)
1671         {
1672             UNICODE_STRING uniFullName;
1673             AFSDirEnumEntry *pDirEnumEntry = NULL;
1674
1675             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1676                           AFS_TRACE_LEVEL_VERBOSE,
1677                           "AFSGetConnectionInfo No connection for full name %wZ\n", &uniFullName);
1678
1679             //
1680             // Drop the lock, we will pick it up again later
1681             //
1682
1683             AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1684
1685             //
1686             // OK, ask the CM about this component name
1687             //
1688
1689             ntStatus = AFSEvaluateTargetByName( NULL,
1690                                                 &AFSGlobalRoot->ObjectInformation,
1691                                                 &uniShareName,
1692                                                 &pDirEnumEntry);
1693
1694             if( !NT_SUCCESS( ntStatus))
1695             {
1696
1697                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1698                               AFS_TRACE_LEVEL_VERBOSE,
1699                               "AFSGetConnectionInfo Evaluation Failed share name %wZ\n",
1700                               uniShareName);
1701
1702                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1703
1704             }
1705
1706             //
1707             // Don't need this
1708             //
1709
1710             AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_3_TAG);
1711
1712             //
1713             // The share name is valid
1714             // Allocate a new node and add it to our list
1715             //
1716             uniFullName.MaximumLength = PAGE_SIZE;
1717             uniFullName.Length = 0;
1718
1719             uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1720                                                                     uniFullName.MaximumLength,
1721                                                                     AFS_NETWORK_PROVIDER_6_TAG);
1722
1723             if( uniFullName.Buffer == NULL)
1724             {
1725
1726                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1727                               AFS_TRACE_LEVEL_VERBOSE,
1728                               "AFSGetConnectionInfo INSUFFICIENT_RESOURCES\n");
1729
1730                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1731             }
1732
1733             uniFullName.Buffer[ 0] = L'\\';
1734             uniFullName.Buffer[ 1] = L'\\';
1735
1736             uniFullName.Length = 2 * sizeof( WCHAR);
1737
1738             RtlCopyMemory( &uniFullName.Buffer[ 2],
1739                            AFSServerName.Buffer,
1740                            AFSServerName.Length);
1741
1742             uniFullName.Length += AFSServerName.Length;
1743
1744             uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)] = L'\\';
1745
1746             uniFullName.Length += sizeof( WCHAR);
1747
1748             RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
1749                            uniShareName.Buffer,
1750                            uniShareName.Length);
1751
1752             uniFullName.Length += uniShareName.Length;
1753
1754             AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
1755                             TRUE);
1756
1757             ntStatus = AFSAddConnectionEx( &uniFullName,
1758                                            RESOURCEDISPLAYTYPE_SHARE,
1759                                            0);
1760
1761             AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
1762
1763             AFSExFreePoolWithTag( uniFullName.Buffer, 0);
1764
1765             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1766                           AFS_TRACE_LEVEL_VERBOSE,
1767                           "AFSGetConnectionInfo Acquiring AFSProviderListLock lock %p SHARED %08lX\n",
1768                           &pRDRDevExt->Specific.RDR.ProviderListLock,
1769                           PsGetCurrentThread());
1770
1771             AFSAcquireShared( &pRDRDevExt->Specific.RDR.ProviderListLock,
1772                               TRUE);
1773
1774             if ( NT_SUCCESS( ntStatus) )
1775             {
1776                 //
1777                 // Once again, locate the entry for the share we just created
1778                 //
1779
1780                 pConnection = AFSLocateEnumRootEntry( &uniShareName);
1781             }
1782
1783         }
1784
1785         if( pConnection == NULL)
1786         {
1787
1788             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1789                           AFS_TRACE_LEVEL_ERROR,
1790                           "AFSGetConnectionInfo Failed to locate entry for full name %wZ\n", &uniFullName);
1791
1792             AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1793
1794             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1795         }
1796
1797         //
1798         // Fill in the returned connection info block
1799         //
1800
1801         if( BufferLength < (ULONG)FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1802                                                 pConnection->RemoteName.Length +
1803                                                 pConnection->Comment.Length +
1804                                                 uniRemainingPath.Length)
1805         {
1806
1807             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1808                           AFS_TRACE_LEVEL_VERBOSE,
1809                           "AFSGetConnectionInfo Buffer too small for full name %wZ\n",
1810                           &uniFullName);
1811
1812             AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1813
1814             try_return( ntStatus = STATUS_BUFFER_OVERFLOW);
1815         }
1816
1817         AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1818                       AFS_TRACE_LEVEL_VERBOSE,
1819                       "AFSGetConnectionInfo Returning entry Scope %08lX partial name %wZ full name %wZ\n",
1820                       pConnection->Scope, &pConnection->RemoteName, &uniFullName);
1821
1822         ConnectCB->RemoteNameLength = pConnection->RemoteName.Length;
1823
1824         if( !bEnumerationEntry)
1825         {
1826
1827             RtlCopyMemory( ConnectCB->RemoteName,
1828                            uniFullName.Buffer,
1829                            pConnection->RemoteName.Length);
1830         }
1831         else
1832         {
1833
1834             RtlCopyMemory( ConnectCB->RemoteName,
1835                            pConnection->RemoteName.Buffer,
1836                            pConnection->RemoteName.Length);
1837         }
1838
1839         ConnectCB->LocalName = pConnection->LocalName;
1840
1841         ConnectCB->Type = pConnection->Type;
1842
1843         ConnectCB->Scope = pConnection->Scope;
1844
1845         ConnectCB->DisplayType = pConnection->DisplayType;
1846
1847         ConnectCB->Usage = pConnection->Usage;
1848
1849         ConnectCB->CommentLength = pConnection->Comment.Length;
1850
1851         ConnectCB->RemainingPathLength = uniRemainingPathLocal.Length;
1852
1853         AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1854                       AFS_TRACE_LEVEL_VERBOSE,
1855                       "AFSGetConnectionInfo Returning lengths: remote %u comment %u remaining %u\n",
1856                       ConnectCB->RemoteNameLength,
1857                       ConnectCB->CommentLength,
1858                       ConnectCB->RemainingPathLength);
1859
1860         if( ConnectCB->CommentLength > 0)
1861         {
1862
1863             ConnectCB->CommentOffset = (ULONG)(FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1864                                                              ConnectCB->RemoteNameLength);
1865
1866             RtlCopyMemory( (void *)((char *)ConnectCB + ConnectCB->CommentOffset),
1867                            pConnection->Comment.Buffer,
1868                            ConnectCB->CommentLength);
1869         }
1870
1871         if ( ConnectCB->RemainingPathLength > 0 )
1872         {
1873
1874             ConnectCB->RemainingPathOffset = (ULONG)(FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1875                                                                    ConnectCB->RemoteNameLength +
1876                                                                    ConnectCB->CommentLength);
1877
1878             RtlCopyMemory( (void *)((char *)ConnectCB + ConnectCB->RemainingPathOffset),
1879                            uniRemainingPathLocal.Buffer,
1880                            uniRemainingPathLocal.Length);
1881         }
1882
1883         *ReturnOutputBufferLength = FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1884                                                   ConnectCB->RemoteNameLength +
1885                                                   ConnectCB->CommentLength +
1886                                                   ConnectCB->RemainingPathLength;
1887
1888         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1889
1890 try_exit:
1891
1892         if ( uniRemainingPathLocal.Buffer )
1893         {
1894
1895             AFSExFreePoolWithTag( uniRemainingPathLocal.Buffer, 0);
1896         }
1897     }
1898
1899     return ntStatus;
1900 }
1901
1902 BOOLEAN
1903 AFSIsDriveMapped( IN WCHAR DriveMapping)
1904 {
1905
1906     BOOLEAN bDriveMapped = FALSE;
1907     AFSProviderConnectionCB *pConnection = NULL;
1908     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1909
1910     __Enter
1911     {
1912
1913         AFSAcquireShared( &pRDRDevExt->Specific.RDR.ProviderListLock,
1914                           TRUE);
1915
1916         pConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
1917
1918         while( pConnection != NULL)
1919         {
1920
1921             if( pConnection->LocalName != L'\0' &&
1922                 RtlUpcaseUnicodeChar( pConnection->LocalName) == RtlUpcaseUnicodeChar( DriveMapping))
1923             {
1924
1925                 bDriveMapped = TRUE;
1926
1927                 break;
1928             }
1929
1930             pConnection = pConnection->fLink;
1931         }
1932
1933         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1934     }
1935
1936     return bDriveMapped;
1937 }