466084fc8e60d7e39c7e80184131126d0819a8bc
[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->LocalName != L'\0')
552         {
553
554             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
555                           AFS_TRACE_LEVEL_VERBOSE,
556                           "AFSGetConnection Local %C authentication id %I64X\n",
557                           ConnectCB->LocalName,
558                           ConnectCB->AuthenticationId.QuadPart));
559         }
560         else
561         {
562
563             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
564                           AFS_TRACE_LEVEL_VERBOSE,
565                           "AFSGetConnection Local (NULL) authentication id %I64X\n",
566                           ConnectCB->AuthenticationId.QuadPart));
567         }
568
569         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
570                       AFS_TRACE_LEVEL_VERBOSE,
571                       "AFSGetConnection Acquiring AFSProviderListLock lock %p SHARED %08lX\n",
572                       &pRDRDevExt->Specific.RDR.ProviderListLock,
573                       PsGetCurrentThread()));
574
575         if( ConnectCB->AuthenticationId.QuadPart == 0)
576         {
577
578             ConnectCB->AuthenticationId = AFSGetAuthenticationId();
579
580             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
581                           AFS_TRACE_LEVEL_VERBOSE,
582                           "AFSGetConnection Retrieved authentication id %I64X\n",
583                           ConnectCB->AuthenticationId.QuadPart));
584         }
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->LocalName != L'\0')
1470         {
1471
1472             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1473                           AFS_TRACE_LEVEL_VERBOSE,
1474                           "AFSGetConnectionInfo remote name %wZ Local %C authentication id %I64X\n",
1475                           &uniRemoteName,
1476                           ConnectCB->LocalName,
1477                           ConnectCB->AuthenticationId.QuadPart));
1478         }
1479         else
1480         {
1481
1482             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1483                           AFS_TRACE_LEVEL_VERBOSE,
1484                           "AFSGetConnectionInfo remote name %wZ Local (NULL) authentication id %I64X\n",
1485                           &uniRemoteName,
1486                           ConnectCB->AuthenticationId.QuadPart));
1487         }
1488
1489         if( AFSGlobalRoot == NULL)
1490         {
1491
1492             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1493                           AFS_TRACE_LEVEL_ERROR,
1494                           "AFSGetConnectionInfo Global root not yet initialized\n"));
1495
1496             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1497         }
1498
1499         uniFullName = uniRemoteName;
1500
1501         if( uniRemoteName.Buffer[ 0] == L'\\' &&
1502             uniRemoteName.Buffer[ 1] == L'\\')
1503         {
1504
1505             uniRemoteName.Buffer = &uniRemoteName.Buffer[ 1];
1506
1507             uniRemoteName.Length -= sizeof( WCHAR);
1508         }
1509
1510         if( uniRemoteName.Buffer[ (uniRemoteName.Length/sizeof( WCHAR)) - 1] == L'\\')
1511         {
1512
1513             uniRemoteName.Length -= sizeof( WCHAR);
1514
1515             uniFullName.Length -= sizeof( WCHAR);
1516         }
1517
1518         AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1519                       AFS_TRACE_LEVEL_VERBOSE,
1520                       "AFSGetConnectionInfo Processing name %wZ\n",
1521                       &uniFullName));
1522
1523         FsRtlDissectName( uniRemoteName,
1524                           &uniServerName,
1525                           &uniRemainingPath);
1526
1527         uniRemoteName = uniRemainingPath;
1528
1529         if( uniRemoteName.Length > 0)
1530         {
1531
1532             FsRtlDissectName( uniRemoteName,
1533                               &uniShareName,
1534                               &uniRemainingPath);
1535         }
1536
1537         if( RtlCompareUnicodeString( &uniServerName,
1538                                      &AFSServerName,
1539                                      TRUE) != 0)
1540         {
1541
1542             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1543         }
1544
1545         if ( uniRemainingPath.Length > 0 )
1546         {
1547
1548             //
1549             // Add back in the leading \ since it was stripped off above
1550             //
1551
1552             uniRemainingPath.Length += sizeof( WCHAR);
1553             if( uniRemainingPath.Length > uniRemainingPath.MaximumLength)
1554             {
1555                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
1556             }
1557
1558             uniRemainingPath.Buffer--;
1559
1560             uniRemainingPathLocal.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1561                                                                               uniRemainingPath.Length,
1562                                                                               AFS_NETWORK_PROVIDER_5_TAG);
1563
1564             if( uniRemainingPathLocal.Buffer == NULL)
1565             {
1566
1567                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1568                               AFS_TRACE_LEVEL_VERBOSE,
1569                               "AFSGetConnectionInfo INSUFFICIENT_RESOURCES\n"));
1570
1571                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1572             }
1573
1574             uniRemainingPathLocal.MaximumLength = uniRemainingPath.Length;
1575             uniRemainingPathLocal.Length = uniRemainingPath.Length;
1576
1577             RtlCopyMemory( uniRemainingPathLocal.Buffer,
1578                            uniRemainingPath.Buffer,
1579                            uniRemainingPath.Length);
1580         }
1581
1582         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1583                       AFS_TRACE_LEVEL_VERBOSE,
1584                       "AFSGetConnectionInfo Acquiring AFSProviderListLock lock %p SHARED %08lX\n",
1585                       &pRDRDevExt->Specific.RDR.ProviderListLock,
1586                       PsGetCurrentThread()));
1587
1588         AFSAcquireShared( &pRDRDevExt->Specific.RDR.ProviderListLock,
1589                           TRUE);
1590
1591         //
1592         // If this is the server then return information about the
1593         // server entry
1594         //
1595
1596         if( uniShareName.Length == 0 &&
1597             RtlCompareUnicodeString( &uniServerName,
1598                                      &AFSServerName,
1599                                      TRUE) == 0)
1600         {
1601
1602             pConnection = pRDRDevExt->Specific.RDR.ProviderEnumerationList;
1603         }
1604         else
1605         {
1606
1607             //
1608             // See if we can locate it on our connection list
1609             //
1610
1611             pConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
1612
1613             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1614                           AFS_TRACE_LEVEL_VERBOSE,
1615                           "AFSGetConnectionInfo Searching for full name %wZ\n",
1616                           &uniFullName));
1617
1618             while( pConnection != NULL)
1619             {
1620
1621                 if( usMaxNameLen < pConnection->RemoteName.Length &&
1622                     pConnection->RemoteName.Length <= uniFullName.Length)
1623                 {
1624
1625                     usNameLen = uniFullName.Length;
1626
1627                     uniFullName.Length = pConnection->RemoteName.Length;
1628
1629                     if( pConnection->AuthenticationId.QuadPart == ConnectCB->AuthenticationId.QuadPart &&
1630                         RtlCompareUnicodeString( &uniFullName,
1631                                                  &pConnection->RemoteName,
1632                                                  TRUE) == 0)
1633                     {
1634
1635                         usMaxNameLen = pConnection->RemoteName.Length;
1636
1637                         pBestMatch = pConnection;
1638
1639                         AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1640                                       AFS_TRACE_LEVEL_VERBOSE,
1641                                       "AFSGetConnectionInfo Found match for %wZ\n",
1642                                       &pConnection->RemoteName));
1643                     }
1644
1645                     uniFullName.Length = usNameLen;
1646                 }
1647
1648                 pConnection = pConnection->fLink;
1649             }
1650
1651             pConnection = pBestMatch;
1652
1653             if( pConnection != NULL)
1654             {
1655
1656                 bEnumerationEntry = TRUE;
1657
1658                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1659                               AFS_TRACE_LEVEL_VERBOSE,
1660                               "AFSGetConnectionInfo Using best match for %wZ\n",
1661                               &pConnection->RemoteName));
1662             }
1663
1664             if( pConnection == NULL)
1665             {
1666
1667                 //
1668                 // Locate the entry for the share
1669                 //
1670
1671                 pConnection = AFSLocateEnumRootEntry( &uniShareName);
1672             }
1673         }
1674
1675         if( pConnection == NULL)
1676         {
1677             UNICODE_STRING uniFullName;
1678             AFSDirEnumEntry *pDirEnumEntry = NULL;
1679
1680             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1681                           AFS_TRACE_LEVEL_VERBOSE,
1682                           "AFSGetConnectionInfo No connection for full name %wZ\n",
1683                           &uniFullName));
1684
1685             //
1686             // Drop the lock, we will pick it up again later
1687             //
1688
1689             AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1690
1691             //
1692             // OK, ask the CM about this component name
1693             //
1694
1695             ntStatus = AFSEvaluateTargetByName( NULL,
1696                                                 &AFSGlobalRoot->ObjectInformation,
1697                                                 &uniShareName,
1698                                                 0,
1699                                                 &pDirEnumEntry);
1700
1701             if( !NT_SUCCESS( ntStatus))
1702             {
1703
1704                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1705                               AFS_TRACE_LEVEL_VERBOSE,
1706                               "AFSGetConnectionInfo Evaluation Failed share name %wZ\n",
1707                               uniShareName));
1708
1709                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1710
1711             }
1712
1713             //
1714             // Don't need this
1715             //
1716
1717             AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_3_TAG);
1718
1719             //
1720             // The share name is valid
1721             // Allocate a new node and add it to our list
1722             //
1723             uniFullName.MaximumLength = PAGE_SIZE;
1724             uniFullName.Length = 0;
1725
1726             uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1727                                                                     uniFullName.MaximumLength,
1728                                                                     AFS_NETWORK_PROVIDER_6_TAG);
1729
1730             if( uniFullName.Buffer == NULL)
1731             {
1732
1733                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1734                               AFS_TRACE_LEVEL_VERBOSE,
1735                               "AFSGetConnectionInfo INSUFFICIENT_RESOURCES\n"));
1736
1737                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1738             }
1739
1740             uniFullName.Buffer[ 0] = L'\\';
1741             uniFullName.Buffer[ 1] = L'\\';
1742
1743             uniFullName.Length = 2 * sizeof( WCHAR);
1744
1745             RtlCopyMemory( &uniFullName.Buffer[ 2],
1746                            AFSServerName.Buffer,
1747                            AFSServerName.Length);
1748
1749             uniFullName.Length += AFSServerName.Length;
1750
1751             uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)] = L'\\';
1752
1753             uniFullName.Length += sizeof( WCHAR);
1754
1755             RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
1756                            uniShareName.Buffer,
1757                            uniShareName.Length);
1758
1759             uniFullName.Length += uniShareName.Length;
1760
1761             AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
1762                             TRUE);
1763
1764             ntStatus = AFSAddConnectionEx( &uniFullName,
1765                                            RESOURCEDISPLAYTYPE_SHARE,
1766                                            0);
1767
1768             AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
1769
1770             AFSExFreePoolWithTag( uniFullName.Buffer, 0);
1771
1772             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1773                           AFS_TRACE_LEVEL_VERBOSE,
1774                           "AFSGetConnectionInfo Acquiring AFSProviderListLock lock %p SHARED %08lX\n",
1775                           &pRDRDevExt->Specific.RDR.ProviderListLock,
1776                           PsGetCurrentThread()));
1777
1778             AFSAcquireShared( &pRDRDevExt->Specific.RDR.ProviderListLock,
1779                               TRUE);
1780
1781             if ( NT_SUCCESS( ntStatus) )
1782             {
1783                 //
1784                 // Once again, locate the entry for the share we just created
1785                 //
1786
1787                 pConnection = AFSLocateEnumRootEntry( &uniShareName);
1788             }
1789
1790         }
1791
1792         if( pConnection == NULL)
1793         {
1794
1795             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1796                           AFS_TRACE_LEVEL_ERROR,
1797                           "AFSGetConnectionInfo Failed to locate entry for full name %wZ\n",
1798                           &uniFullName));
1799
1800             AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1801
1802             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1803         }
1804
1805         //
1806         // Fill in the returned connection info block
1807         //
1808
1809         if( BufferLength < (ULONG)FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1810                                                 pConnection->RemoteName.Length +
1811                                                 pConnection->Comment.Length +
1812                                                 uniRemainingPath.Length)
1813         {
1814
1815             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1816                           AFS_TRACE_LEVEL_VERBOSE,
1817                           "AFSGetConnectionInfo Buffer too small for full name %wZ\n",
1818                           &uniFullName));
1819
1820             AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1821
1822             try_return( ntStatus = STATUS_BUFFER_OVERFLOW);
1823         }
1824
1825         AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1826                       AFS_TRACE_LEVEL_VERBOSE,
1827                       "AFSGetConnectionInfo Returning entry Scope %08lX partial name %wZ full name %wZ\n",
1828                       pConnection->Scope, &pConnection->RemoteName, &uniFullName));
1829
1830         ConnectCB->RemoteNameLength = pConnection->RemoteName.Length;
1831
1832         if( !bEnumerationEntry)
1833         {
1834
1835             RtlCopyMemory( ConnectCB->RemoteName,
1836                            uniFullName.Buffer,
1837                            pConnection->RemoteName.Length);
1838         }
1839         else
1840         {
1841
1842             RtlCopyMemory( ConnectCB->RemoteName,
1843                            pConnection->RemoteName.Buffer,
1844                            pConnection->RemoteName.Length);
1845         }
1846
1847         ConnectCB->LocalName = pConnection->LocalName;
1848
1849         ConnectCB->Type = pConnection->Type;
1850
1851         ConnectCB->Scope = pConnection->Scope;
1852
1853         ConnectCB->DisplayType = pConnection->DisplayType;
1854
1855         ConnectCB->Usage = pConnection->Usage;
1856
1857         ConnectCB->CommentLength = pConnection->Comment.Length;
1858
1859         ConnectCB->RemainingPathLength = uniRemainingPathLocal.Length;
1860
1861         AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1862                       AFS_TRACE_LEVEL_VERBOSE,
1863                       "AFSGetConnectionInfo Returning lengths: remote %u comment %u remaining %u\n",
1864                       ConnectCB->RemoteNameLength,
1865                       ConnectCB->CommentLength,
1866                       ConnectCB->RemainingPathLength));
1867
1868         if( ConnectCB->CommentLength > 0)
1869         {
1870
1871             ConnectCB->CommentOffset = (ULONG)(FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1872                                                              ConnectCB->RemoteNameLength);
1873
1874             RtlCopyMemory( (void *)((char *)ConnectCB + ConnectCB->CommentOffset),
1875                            pConnection->Comment.Buffer,
1876                            ConnectCB->CommentLength);
1877         }
1878
1879         if ( ConnectCB->RemainingPathLength > 0 )
1880         {
1881
1882             ConnectCB->RemainingPathOffset = (ULONG)(FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1883                                                                    ConnectCB->RemoteNameLength +
1884                                                                    ConnectCB->CommentLength);
1885
1886             RtlCopyMemory( (void *)((char *)ConnectCB + ConnectCB->RemainingPathOffset),
1887                            uniRemainingPathLocal.Buffer,
1888                            uniRemainingPathLocal.Length);
1889         }
1890
1891         *ReturnOutputBufferLength = FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1892                                                   ConnectCB->RemoteNameLength +
1893                                                   ConnectCB->CommentLength +
1894                                                   ConnectCB->RemainingPathLength;
1895
1896         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1897
1898 try_exit:
1899
1900         if ( uniRemainingPathLocal.Buffer )
1901         {
1902
1903             AFSExFreePoolWithTag( uniRemainingPathLocal.Buffer, 0);
1904         }
1905     }
1906
1907     return ntStatus;
1908 }
1909
1910 BOOLEAN
1911 AFSIsDriveMapped( IN WCHAR DriveMapping)
1912 {
1913
1914     BOOLEAN bDriveMapped = FALSE;
1915     AFSProviderConnectionCB *pConnection = NULL;
1916     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1917
1918     __Enter
1919     {
1920
1921         AFSAcquireShared( &pRDRDevExt->Specific.RDR.ProviderListLock,
1922                           TRUE);
1923
1924         pConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
1925
1926         while( pConnection != NULL)
1927         {
1928
1929             if( pConnection->LocalName != L'\0' &&
1930                 RtlUpcaseUnicodeChar( pConnection->LocalName) == RtlUpcaseUnicodeChar( DriveMapping))
1931             {
1932
1933                 bDriveMapped = TRUE;
1934
1935                 break;
1936             }
1937
1938             pConnection = pConnection->fLink;
1939         }
1940
1941         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1942     }
1943
1944     return bDriveMapped;
1945 }