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