Windows: Support correct status codes from service
[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     USHORT usIndex = 0;
51     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
52
53     __Enter
54     {
55
56         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
57                       AFS_TRACE_LEVEL_VERBOSE,
58                       "AFSAddConnection Acquiring AFSProviderListLock lock %08lX EXCL %08lX\n",
59                       &pRDRDevExt->Specific.RDR.ProviderListLock,
60                       PsGetCurrentThread());
61
62         if( ConnectCB->AuthenticationId.QuadPart == 0)
63         {
64
65             ConnectCB->AuthenticationId = AFSGetAuthenticationId();
66
67             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
68                           AFS_TRACE_LEVEL_VERBOSE,
69                           "AFSAddConnection Retrieved authentication id %I64X\n",
70                           ConnectCB->AuthenticationId.QuadPart);
71         }
72
73         AFSAcquireExcl( &pRDRDevExt->Specific.RDR.ProviderListLock,
74                         TRUE);
75
76         //
77         // Look for the connection
78         //
79
80         uniRemoteName.Length = (USHORT)ConnectCB->RemoteNameLength;
81         uniRemoteName.MaximumLength = uniRemoteName.Length;
82
83         uniRemoteName.Buffer = ConnectCB->RemoteName;
84
85         //
86         // Strip off any trailing slashes
87         //
88
89         if( uniRemoteName.Buffer[ (uniRemoteName.Length/sizeof( WCHAR)) - 1] == L'\\')
90         {
91
92             uniRemoteName.Length -= sizeof( WCHAR);
93         }
94
95         pConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
96
97         while( pConnection != NULL)
98         {
99
100             if( pConnection->LocalName == ConnectCB->LocalName &&
101                 pConnection->AuthenticationId.QuadPart == ConnectCB->AuthenticationId.QuadPart &&
102                 RtlCompareUnicodeString( &uniRemoteName,
103                                          &pConnection->RemoteName,
104                                          TRUE) == 0)
105             {
106
107                 break;
108             }
109
110             pConnection = pConnection->fLink;
111         }
112
113         if( pConnection != NULL)
114         {
115
116             if( ConnectCB->LocalName != L'\0')
117             {
118
119                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
120                               AFS_TRACE_LEVEL_VERBOSE,
121                               "AFSAddConnection ALREADY_CONNECTED remote name %wZ Local %C authentication id %I64X\n",
122                               &uniRemoteName,
123                               ConnectCB->LocalName,
124                               ConnectCB->AuthenticationId.QuadPart);
125             }
126             else
127             {
128
129                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
130                               AFS_TRACE_LEVEL_VERBOSE,
131                               "AFSAddConnection ALREADY_CONNECTED remote name %wZ Local (NULL) authentication id %I64X\n",
132                               &uniRemoteName,
133                               ConnectCB->AuthenticationId.QuadPart);
134             }
135
136             *ResultStatus = WN_ALREADY_CONNECTED;
137
138             *ReturnOutputBufferLength = sizeof( ULONG);
139
140             try_return( ntStatus);
141         }
142
143         //
144         // Validate the remote name
145         //
146
147         if( uniRemoteName.Length > 2 * sizeof( WCHAR) &&
148             uniRemoteName.Buffer[ 0] == L'\\' &&
149             uniRemoteName.Buffer[ 1] == L'\\')
150         {
151
152             uniRemoteName.Buffer = &uniRemoteName.Buffer[ 2];
153
154             uniRemoteName.Length -= (2 * sizeof( WCHAR));
155         }
156
157         if( uniRemoteName.Length >= AFSServerName.Length)
158         {
159
160             USHORT usLength = uniRemoteName.Length;
161
162             if (uniRemoteName.Buffer[AFSServerName.Length/sizeof( WCHAR)] != L'\\')
163             {
164
165                 if( ConnectCB->LocalName != L'\0')
166                 {
167
168                     AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
169                                   AFS_TRACE_LEVEL_VERBOSE,
170                                   "AFSAddConnection BAD_NETNAME 1 remote name %wZ Local %C authentication id %I64X\n",
171                                   &uniRemoteName,
172                                   ConnectCB->LocalName,
173                                   ConnectCB->AuthenticationId.QuadPart);
174                 }
175                 else
176                 {
177
178                     AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
179                                   AFS_TRACE_LEVEL_VERBOSE,
180                                   "AFSAddConnection BAD_NETNAME 1 remote name %wZ Local (NULL) authentication id %I64X\n",
181                                   &uniRemoteName,
182                                   ConnectCB->AuthenticationId.QuadPart);
183                 }
184
185                 *ResultStatus = WN_BAD_NETNAME;
186
187                 *ReturnOutputBufferLength = sizeof( ULONG);
188
189                 try_return( ntStatus = STATUS_SUCCESS);
190             }
191
192             uniRemoteName.Length = AFSServerName.Length;
193
194             if( RtlCompareUnicodeString( &AFSServerName,
195                                          &uniRemoteName,
196                                          TRUE) != 0)
197             {
198
199                 if( ConnectCB->LocalName != L'\0')
200                 {
201
202                     AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
203                                   AFS_TRACE_LEVEL_VERBOSE,
204                                   "AFSAddConnection BAD_NETNAME 2 remote name %wZ Local %C authentication id %I64X\n",
205                                   &uniRemoteName,
206                                   ConnectCB->LocalName,
207                                   ConnectCB->AuthenticationId.QuadPart);
208                 }
209                 else
210                 {
211
212                     AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
213                                   AFS_TRACE_LEVEL_VERBOSE,
214                                   "AFSAddConnection BAD_NETNAME 2 remote name %wZ Local (NULL) authentication id %I64X\n",
215                                   &uniRemoteName,
216                                   ConnectCB->AuthenticationId.QuadPart);
217                 }
218
219                 *ResultStatus = WN_BAD_NETNAME;
220
221                 *ReturnOutputBufferLength = sizeof( ULONG);
222
223                 try_return( ntStatus = STATUS_SUCCESS);
224             }
225
226             uniRemoteName.Length = usLength;
227         }
228         else
229         {
230
231             if( ConnectCB->LocalName != L'\0')
232             {
233
234                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
235                               AFS_TRACE_LEVEL_VERBOSE,
236                               "AFSAddConnection BAD_NETNAME 3 remote name %wZ Local %C authentication id %I64X\n",
237                               &uniRemoteName,
238                               ConnectCB->LocalName,
239                               ConnectCB->AuthenticationId.QuadPart);
240             }
241             else
242             {
243
244                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
245                               AFS_TRACE_LEVEL_VERBOSE,
246                               "AFSAddConnection BAD_NETNAME 3 remote name %wZ Local (NULL) authentication id %I64X\n",
247                               &uniRemoteName,
248                               ConnectCB->AuthenticationId.QuadPart);
249             }
250
251             *ResultStatus = WN_BAD_NETNAME;
252
253             *ReturnOutputBufferLength = sizeof( ULONG);
254
255             try_return( ntStatus = STATUS_SUCCESS);
256         }
257
258         uniRemoteName.Length = (USHORT)ConnectCB->RemoteNameLength;
259         uniRemoteName.MaximumLength = uniRemoteName.Length;
260
261         uniRemoteName.Buffer = ConnectCB->RemoteName;
262
263         //
264         // Strip off any trailing slashes
265         //
266
267         if( uniRemoteName.Buffer[ (uniRemoteName.Length/sizeof( WCHAR)) - 1] == L'\\')
268         {
269
270             uniRemoteName.Length -= sizeof( WCHAR);
271         }
272
273         //
274         // Allocate a new node and add it to our list
275         //
276
277         pConnection = (AFSProviderConnectionCB *)AFSExAllocatePoolWithTag( PagedPool,
278                                                                            sizeof( AFSProviderConnectionCB) +
279                                                                                             uniRemoteName.Length,
280                                                                            AFS_PROVIDER_CB);
281
282         if( pConnection == NULL)
283         {
284
285             *ResultStatus = WN_OUT_OF_MEMORY;
286
287             *ReturnOutputBufferLength = sizeof( ULONG);
288
289             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
290         }
291
292         RtlZeroMemory( pConnection,
293                        sizeof( AFSProviderConnectionCB) + uniRemoteName.Length);
294
295         pConnection->LocalName = ConnectCB->LocalName;
296
297         pConnection->RemoteName.Length = uniRemoteName.Length;
298         pConnection->RemoteName.MaximumLength = pConnection->RemoteName.Length;
299
300         pConnection->RemoteName.Buffer = (WCHAR *)((char *)pConnection + sizeof( AFSProviderConnectionCB));
301
302         RtlCopyMemory( pConnection->RemoteName.Buffer,
303                        uniRemoteName.Buffer,
304                        pConnection->RemoteName.Length);
305
306         pConnection->Type = ConnectCB->Type;
307
308         pConnection->AuthenticationId = ConnectCB->AuthenticationId;
309
310         if( ConnectCB->LocalName != L'\0')
311         {
312
313             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
314                           AFS_TRACE_LEVEL_VERBOSE,
315                           "AFSAddConnection Adding connection remote name %wZ Local %C authentication id %I64X\n",
316                           &uniRemoteName,
317                           ConnectCB->LocalName,
318                           ConnectCB->AuthenticationId.QuadPart);
319         }
320         else
321         {
322
323             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
324                           AFS_TRACE_LEVEL_VERBOSE,
325                           "AFSAddConnection Adding connection remote name %wZ Local (NULL) authentication id %I64X\n",
326                           &uniRemoteName,
327                           ConnectCB->AuthenticationId.QuadPart);
328         }
329
330         //
331         // Point to the component portion of the name
332         //
333
334         pConnection->ComponentName.Length = 0;
335         pConnection->ComponentName.MaximumLength = 0;
336
337         pConnection->ComponentName.Buffer = &pConnection->RemoteName.Buffer[ (pConnection->RemoteName.Length/sizeof( WCHAR)) - 1];
338
339         while( pConnection->ComponentName.Length <= pConnection->RemoteName.Length)
340         {
341
342             if( pConnection->ComponentName.Buffer[ 0] == L'\\')
343             {
344
345                 pConnection->ComponentName.Buffer++;
346
347                 break;
348             }
349
350             pConnection->ComponentName.Length += sizeof( WCHAR);
351             pConnection->ComponentName.MaximumLength += sizeof( WCHAR);
352
353             pConnection->ComponentName.Buffer--;
354         }
355
356         //
357         // Go initialize the information about the connection
358         //
359
360         AFSInitializeConnectionInfo( pConnection,
361                                      (ULONG)-1);
362
363         //
364         // Insert the entry into our list
365         //
366
367         if( pRDRDevExt->Specific.RDR.ProviderConnectionList == NULL)
368         {
369
370             pRDRDevExt->Specific.RDR.ProviderConnectionList = pConnection;
371         }
372         else
373         {
374
375             //
376             // Get the end of the list
377             //
378
379             pLastConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
380
381             while( pLastConnection->fLink != NULL)
382             {
383
384                 pLastConnection = pLastConnection->fLink;
385             }
386
387             pLastConnection->fLink = pConnection;
388         }
389
390         *ResultStatus = WN_SUCCESS;
391
392         *ReturnOutputBufferLength = sizeof( ULONG);
393
394 try_exit:
395
396         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
397
398     }
399
400     return ntStatus;
401 }
402
403 NTSTATUS
404 AFSCancelConnection( IN AFSNetworkProviderConnectionCB *ConnectCB,
405                      IN OUT AFSCancelConnectionResultCB *ConnectionResult,
406                      IN OUT ULONG_PTR *ReturnOutputBufferLength)
407 {
408
409     NTSTATUS ntStatus = STATUS_SUCCESS;
410     AFSProviderConnectionCB *pConnection = NULL, *pLastConnection = NULL;
411     UNICODE_STRING uniRemoteName;
412     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
413
414     __Enter
415     {
416
417         ConnectionResult->Version = AFS_NETWORKPROVIDER_INTERFACE_VERSION_1;
418
419         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
420                       AFS_TRACE_LEVEL_VERBOSE,
421                       "AFSCancelConnection Acquiring AFSProviderListLock lock %08lX EXCL %08lX\n",
422                       &pRDRDevExt->Specific.RDR.ProviderListLock,
423                       PsGetCurrentThread());
424
425         if( ConnectCB->AuthenticationId.QuadPart == 0)
426         {
427
428             ConnectCB->AuthenticationId = AFSGetAuthenticationId();
429
430             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
431                           AFS_TRACE_LEVEL_VERBOSE,
432                           "AFSCancelConnection Retrieved authentication id %I64X\n",
433                           ConnectCB->AuthenticationId.QuadPart);
434         }
435
436         AFSAcquireExcl( &pRDRDevExt->Specific.RDR.ProviderListLock,
437                         TRUE);
438
439         //
440         // Look for the connection
441         //
442
443         uniRemoteName.Length = (USHORT)ConnectCB->RemoteNameLength;
444         uniRemoteName.MaximumLength = uniRemoteName.Length;
445
446         uniRemoteName.Buffer = NULL;
447
448         if( uniRemoteName.Length > 0)
449         {
450
451             uniRemoteName.Buffer = ConnectCB->RemoteName;
452         }
453
454         pConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
455
456         while( pConnection != NULL)
457         {
458
459             if( ( ConnectCB->LocalName != L'\0' &&
460                   pConnection->LocalName == ConnectCB->LocalName)
461                 ||
462                 ( RtlCompareUnicodeString( &uniRemoteName,
463                                            &pConnection->RemoteName,
464                                            TRUE) == 0))
465             {
466
467                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
468                               AFS_TRACE_LEVEL_VERBOSE,
469                               "AFSCancelConnection Checking remote name %wZ to stored %wZ authentication id %I64X - %I64X\n",
470                               &uniRemoteName,
471                               &pConnection->RemoteName,
472                               ConnectCB->AuthenticationId.QuadPart,
473                               pConnection->AuthenticationId.QuadPart);
474
475                 if( ConnectCB->AuthenticationId.QuadPart == pConnection->AuthenticationId.QuadPart &&
476                     ( ConnectCB->LocalName == L'\0' ||
477                       RtlCompareUnicodeString( &uniRemoteName,
478                                                &pConnection->RemoteName,
479                                                TRUE) == 0))
480                 {
481
482                     break;
483                 }
484             }
485
486             pLastConnection = pConnection;
487
488             pConnection = pConnection->fLink;
489         }
490
491         if( pConnection == NULL)
492         {
493
494             ConnectionResult->Status = WN_NOT_CONNECTED;
495
496             *ReturnOutputBufferLength = sizeof( AFSCancelConnectionResultCB);
497
498             try_return( ntStatus);
499         }
500
501         if( pLastConnection == NULL)
502         {
503
504             pRDRDevExt->Specific.RDR.ProviderConnectionList = pConnection->fLink;
505         }
506         else
507         {
508
509             pLastConnection->fLink = pConnection->fLink;
510         }
511
512         if( pConnection->Comment.Buffer != NULL)
513         {
514
515             AFSExFreePool( pConnection->Comment.Buffer);
516         }
517
518         ConnectionResult->LocalName = pConnection->LocalName;
519
520         AFSExFreePool( pConnection);
521
522         ConnectionResult->Status = WN_SUCCESS;
523
524         *ReturnOutputBufferLength = sizeof( AFSCancelConnectionResultCB);
525
526 try_exit:
527
528         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
529     }
530
531     return ntStatus;
532 }
533
534 NTSTATUS
535 AFSGetConnection( IN AFSNetworkProviderConnectionCB *ConnectCB,
536                   IN OUT WCHAR *RemoteName,
537                   IN ULONG RemoteNameBufferLength,
538                   IN OUT ULONG_PTR *ReturnOutputBufferLength)
539 {
540
541     NTSTATUS ntStatus = STATUS_SUCCESS;
542     AFSProviderConnectionCB *pConnection = NULL;
543     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
544
545     __Enter
546     {
547
548         if( ConnectCB->LocalName != L'\0')
549         {
550
551             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
552                           AFS_TRACE_LEVEL_VERBOSE,
553                           "AFSGetConnection Local %C authentication id %I64X\n",
554                           ConnectCB->LocalName,
555                           ConnectCB->AuthenticationId.QuadPart);
556         }
557         else
558         {
559
560             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
561                           AFS_TRACE_LEVEL_VERBOSE,
562                           "AFSGetConnection Local (NULL) authentication id %I64X\n",
563                           ConnectCB->AuthenticationId.QuadPart);
564         }
565
566         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
567                       AFS_TRACE_LEVEL_VERBOSE,
568                       "AFSGetConnection Acquiring AFSProviderListLock lock %08lX SHARED %08lX\n",
569                       &pRDRDevExt->Specific.RDR.ProviderListLock,
570                       PsGetCurrentThread());
571
572         if( ConnectCB->AuthenticationId.QuadPart == 0)
573         {
574
575             ConnectCB->AuthenticationId = AFSGetAuthenticationId();
576
577             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
578                           AFS_TRACE_LEVEL_VERBOSE,
579                           "AFSGetConnection Retrieved authentication id %I64X\n",
580                           ConnectCB->AuthenticationId.QuadPart);
581         }
582
583         AFSAcquireShared( &pRDRDevExt->Specific.RDR.ProviderListLock,
584                           TRUE);
585
586         //
587         // Look for the connection
588         //
589
590         pConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
591
592         while( pConnection != NULL)
593         {
594
595             if( pConnection->LocalName != L'\0')
596             {
597
598                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
599                               AFS_TRACE_LEVEL_VERBOSE,
600                               "AFSGetConnection Comparing passed in %C to %C authentication id %I64X - %I64X\n",
601                               ConnectCB->LocalName,
602                               pConnection->LocalName,
603                               ConnectCB->AuthenticationId.QuadPart,
604                               pConnection->AuthenticationId.QuadPart);
605             }
606             else
607             {
608
609                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
610                               AFS_TRACE_LEVEL_VERBOSE,
611                               "AFSGetConnection Comparing passed in %C to (NULL) authentication id %I64X - %I64X\n",
612                               ConnectCB->LocalName,
613                               ConnectCB->AuthenticationId.QuadPart,
614                               pConnection->AuthenticationId.QuadPart);
615             }
616
617             if( pConnection->LocalName == ConnectCB->LocalName &&
618                 pConnection->AuthenticationId.QuadPart == ConnectCB->AuthenticationId.QuadPart)
619             {
620
621                 break;
622             }
623
624             pConnection = pConnection->fLink;
625         }
626
627         if( pConnection == NULL)
628         {
629
630             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
631                           AFS_TRACE_LEVEL_VERBOSE,
632                           "AFSGetConnection INVALID_PARAMETER\n");
633
634             try_return( ntStatus = STATUS_INVALID_PARAMETER);
635         }
636
637         if( RemoteNameBufferLength < pConnection->RemoteName.Length)
638         {
639
640             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
641                           AFS_TRACE_LEVEL_VERBOSE,
642                           "AFSGetConnection INSUFFICIENT_RESOURCES\n");
643
644             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
645         }
646
647         RtlCopyMemory( RemoteName,
648                        pConnection->RemoteName.Buffer,
649                        pConnection->RemoteName.Length);
650
651         *ReturnOutputBufferLength = pConnection->RemoteName.Length;
652
653 try_exit:
654
655         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
656     }
657
658     return ntStatus;
659 }
660
661 NTSTATUS
662 AFSListConnections( IN OUT AFSNetworkProviderConnectionCB *ConnectCB,
663                     IN ULONG ConnectionBufferLength,
664                     IN OUT ULONG_PTR *ReturnOutputBufferLength)
665 {
666
667     NTSTATUS ntStatus = STATUS_SUCCESS;
668     AFSProviderConnectionCB *pConnection = NULL, *pRootConnection = NULL;
669     ULONG ulCopiedLength = 0, ulRemainingLength = ConnectionBufferLength;
670     ULONG ulScope, ulType;
671     UNICODE_STRING uniRemoteName, uniServerName, uniShareName, uniRemainingPath;
672     BOOLEAN bGlobalEnumeration = FALSE;
673     ULONG       ulIndex = 0;
674     LARGE_INTEGER liAuthenticationID = {0,0};
675     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
676
677     __Enter
678     {
679
680         //
681         // Save off some data before moving on
682         //
683
684         ulScope = ConnectCB->Scope;
685
686         ulType = ConnectCB->Type;
687
688         if( ConnectCB->AuthenticationId.QuadPart == 0)
689         {
690
691             ConnectCB->AuthenticationId = AFSGetAuthenticationId();
692
693             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
694                           AFS_TRACE_LEVEL_VERBOSE,
695                           "AFSListConnections Retrieved authentication id %I64X\n",
696                           ConnectCB->AuthenticationId.QuadPart);
697         }
698
699         liAuthenticationID.QuadPart = ConnectCB->AuthenticationId.QuadPart;
700
701         uniRemoteName.Length = 0;
702         uniRemoteName.MaximumLength = 0;
703         uniRemoteName.Buffer = NULL;
704
705         uniServerName.Length = 0;
706         uniServerName.MaximumLength = 0;
707         uniServerName.Buffer = NULL;
708
709         uniShareName.Length = 0;
710         uniShareName.MaximumLength = 0;
711         uniShareName.Buffer = NULL;
712
713         if( ConnectCB->RemoteNameLength > 0)
714         {
715
716             uniRemoteName.Length = (USHORT)ConnectCB->RemoteNameLength;
717             uniRemoteName.MaximumLength = uniRemoteName.Length + sizeof( WCHAR);
718
719             uniRemoteName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
720                                                                       uniRemoteName.MaximumLength,
721                                                                       AFS_NETWORK_PROVIDER_1_TAG);
722
723             if( uniRemoteName.Buffer == NULL)
724             {
725
726                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
727             }
728
729             RtlCopyMemory( uniRemoteName.Buffer,
730                            ConnectCB->RemoteName,
731                            uniRemoteName.Length);
732
733             if( uniRemoteName.Buffer[ 0] == L'\\' &&
734                 uniRemoteName.Buffer[ 1] == L'\\')
735             {
736
737                 uniRemoteName.Buffer = &uniRemoteName.Buffer[ 1];
738
739                 uniRemoteName.Length -= sizeof( WCHAR);
740             }
741
742             if( uniRemoteName.Buffer[ (uniRemoteName.Length/sizeof( WCHAR)) - 1] == L'\\')
743             {
744
745                 uniRemoteName.Length -= sizeof( WCHAR);
746             }
747
748             FsRtlDissectName( uniRemoteName,
749                               &uniServerName,
750                               &uniRemainingPath);
751
752             uniRemoteName = uniRemainingPath;
753
754             if( uniRemoteName.Length > 0)
755             {
756
757                 FsRtlDissectName( uniRemoteName,
758                                   &uniShareName,
759                                   &uniRemainingPath);
760             }
761
762             //
763             // If this is an enumeration of the global share name then
764             // adjust it to be the server name itself
765             //
766
767             if( uniShareName.Length == 0 ||
768                 RtlCompareUnicodeString( &uniShareName,
769                                          &AFSGlobalRootName,
770                                          TRUE) == 0)
771             {
772
773                 bGlobalEnumeration = TRUE;
774             }
775         }
776
777         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
778                       AFS_TRACE_LEVEL_VERBOSE,
779                       "AFSListConnections Acquiring AFSProviderListLock lock %08lX 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                 AFSDbgLogMsg( 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                 AFSDbgLogMsg( 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             AFSExFreePool( uniRemoteName.Buffer);
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 uniServerName, 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     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1232     ULONG ulCRC = 0, ulCopiedLength = 0;
1233     AFSDirectoryCB *pShareDirEntry = NULL;
1234     AFSDirectoryCB *pDirEntry = NULL, *pTargetDirEntry = NULL;
1235     ULONG ulIndex = 0;
1236     BOOLEAN bContinueProcessing = TRUE;
1237     AFSFileInfoCB stFileInformation;
1238
1239     __Enter
1240     {
1241
1242         if( AFSGlobalRoot == NULL)
1243         {
1244
1245             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1246                           AFS_TRACE_LEVEL_ERROR,
1247                           "AFSEnumerateConnection Global root not yet initialized\n");
1248
1249             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1250         }
1251
1252         ulCRC = AFSGenerateCRC( &RootConnection->ComponentName,
1253                                 FALSE);
1254
1255         //
1256         // Grab our tree lock shared
1257         //
1258
1259         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1260                       AFS_TRACE_LEVEL_VERBOSE,
1261                       "AFSEnumerateConnection Acquiring GlobalRoot DirectoryNodeHdr.TreeLock lock %08lX SHARED %08lX\n",
1262                       AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
1263                       PsGetCurrentThread());
1264
1265         AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
1266                           TRUE);
1267
1268         //
1269         // Locate the dir entry for this node
1270         //
1271
1272         ntStatus = AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1273                                                    ulCRC,
1274                                                    &pShareDirEntry);
1275
1276         if( pShareDirEntry == NULL ||
1277             !NT_SUCCESS( ntStatus))
1278         {
1279
1280             //
1281             // Perform a case insensitive search
1282             //
1283
1284             ulCRC = AFSGenerateCRC( &RootConnection->ComponentName,
1285                                     TRUE);
1286
1287             ntStatus = AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1288                                                          ulCRC,
1289                                                          &pShareDirEntry);
1290
1291             if( pShareDirEntry == NULL ||
1292                 !NT_SUCCESS( ntStatus))
1293             {
1294
1295                 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
1296
1297                 try_return( ntStatus);
1298             }
1299         }
1300
1301         InterlockedIncrement( &pShareDirEntry->OpenReferenceCount);
1302
1303         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1304                       AFS_TRACE_LEVEL_VERBOSE,
1305                       "AFSEnumerateConnection1 Increment count on %wZ DE %p Ccb %p Cnt %d\n",
1306                       &pShareDirEntry->NameInformation.FileName,
1307                       pShareDirEntry,
1308                       NULL,
1309                       pShareDirEntry->OpenReferenceCount);
1310
1311         AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
1312
1313         //
1314         // Setup the request to evaluate the entry
1315         //
1316
1317         ntStatus = AFSEvaluateRootEntry( pShareDirEntry,
1318                                          &pTargetDirEntry);
1319
1320         if( !NT_SUCCESS( ntStatus))
1321         {
1322
1323             try_return( ntStatus);
1324         }
1325
1326         AFSAcquireShared( pTargetDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1327                           TRUE);
1328
1329         //
1330         // Enumerate the content
1331         //
1332
1333         pDirEntry = pTargetDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
1334
1335         ulIndex = ConnectCB->CurrentIndex;
1336
1337         while( pDirEntry != NULL)
1338         {
1339
1340             if( ulIndex > 0)
1341             {
1342
1343                 ulIndex--;
1344
1345                 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
1346
1347                 continue;
1348             }
1349
1350             if( BufferLength < (ULONG)FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1351                                                                pDirEntry->NameInformation.FileName.Length)
1352             {
1353
1354                 break;
1355             }
1356
1357             ConnectCB->LocalName = L'\0';
1358
1359             ConnectCB->RemoteNameLength = pDirEntry->NameInformation.FileName.Length;
1360
1361             RtlCopyMemory( ConnectCB->RemoteName,
1362                            pDirEntry->NameInformation.FileName.Buffer,
1363                            pDirEntry->NameInformation.FileName.Length);
1364
1365             ConnectCB->Type = RESOURCETYPE_DISK;
1366
1367             ConnectCB->Scope = RESOURCE_CONNECTED;
1368
1369             if( BooleanFlagOn( pDirEntry->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
1370             {
1371
1372                 ConnectCB->DisplayType = RESOURCEDISPLAYTYPE_DIRECTORY;
1373             }
1374             else
1375             {
1376
1377                 ConnectCB->DisplayType = RESOURCEDISPLAYTYPE_FILE;
1378             }
1379
1380             ConnectCB->Usage = 0;
1381
1382             ConnectCB->CommentLength = 0;
1383
1384             ulCopiedLength += FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1385                                                     pDirEntry->NameInformation.FileName.Length;
1386
1387             BufferLength -= FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1388                                                     pDirEntry->NameInformation.FileName.Length;
1389
1390             ConnectCB = (AFSNetworkProviderConnectionCB *)((char *)ConnectCB +
1391                                                             FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1392                                                             ConnectCB->RemoteNameLength);
1393
1394             pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
1395         }
1396
1397         InterlockedDecrement( &pTargetDirEntry->OpenReferenceCount);
1398
1399         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1400                       AFS_TRACE_LEVEL_VERBOSE,
1401                       "AFSEnumerateConnection Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1402                                                     &pTargetDirEntry->NameInformation.FileName,
1403                                                     pTargetDirEntry,
1404                                                     NULL,
1405                                                     pTargetDirEntry->OpenReferenceCount);
1406
1407         *CopiedLength = ulCopiedLength;
1408
1409         AFSReleaseResource( pTargetDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1410
1411 try_exit:
1412
1413         if( pShareDirEntry != NULL)
1414         {
1415             InterlockedDecrement( &pShareDirEntry->OpenReferenceCount);
1416         }
1417     }
1418
1419     return ntStatus;
1420 }
1421
1422 NTSTATUS
1423 AFSGetConnectionInfo( IN AFSNetworkProviderConnectionCB *ConnectCB,
1424                       IN ULONG BufferLength,
1425                       IN OUT ULONG_PTR *ReturnOutputBufferLength)
1426 {
1427
1428     NTSTATUS ntStatus = STATUS_SUCCESS;
1429     AFSProviderConnectionCB *pConnection = NULL, *pBestMatch = NULL;
1430     UNICODE_STRING uniRemoteName, uniServerName, uniShareName, uniRemainingPath, uniFullName, uniRemainingPathLocal;
1431     USHORT usNameLen = 0, usMaxNameLen = 0;
1432     BOOLEAN bEnumerationEntry = FALSE;
1433     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1434
1435     __Enter
1436     {
1437
1438         uniServerName.Length = 0;
1439         uniServerName.MaximumLength = 0;
1440         uniServerName.Buffer = NULL;
1441
1442         uniShareName.Length = 0;
1443         uniShareName.MaximumLength = 0;
1444         uniShareName.Buffer = NULL;
1445
1446         uniRemainingPathLocal.Length = 0;
1447         uniRemainingPathLocal.MaximumLength = 0;
1448         uniRemainingPathLocal.Buffer = NULL;
1449
1450         uniRemoteName.Length = (USHORT)ConnectCB->RemoteNameLength;
1451         uniRemoteName.MaximumLength = uniRemoteName.Length + sizeof( WCHAR);
1452         uniRemoteName.Buffer = (WCHAR *)ConnectCB->RemoteName;
1453
1454         if( ConnectCB->LocalName != L'\0')
1455         {
1456
1457             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1458                           AFS_TRACE_LEVEL_VERBOSE,
1459                           "AFSGetConnectionInfo remote name %wZ Local %C authentication id %I64X\n",
1460                           &uniRemoteName,
1461                           ConnectCB->LocalName,
1462                           ConnectCB->AuthenticationId.QuadPart);
1463         }
1464         else
1465         {
1466
1467             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1468                           AFS_TRACE_LEVEL_VERBOSE,
1469                           "AFSGetConnectionInfo remote name %wZ Local (NULL) authentication id %I64X\n",
1470                           &uniRemoteName,
1471                           ConnectCB->AuthenticationId.QuadPart);
1472         }
1473
1474         if( AFSGlobalRoot == NULL)
1475         {
1476
1477             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1478                           AFS_TRACE_LEVEL_ERROR,
1479                           "AFSGetConnectionInfo Global root not yet initialized\n");
1480
1481             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1482         }
1483
1484                 uniFullName = uniRemoteName;
1485
1486         if( uniRemoteName.Buffer[ 0] == L'\\' &&
1487             uniRemoteName.Buffer[ 1] == L'\\')
1488         {
1489
1490             uniRemoteName.Buffer = &uniRemoteName.Buffer[ 1];
1491
1492             uniRemoteName.Length -= sizeof( WCHAR);
1493         }
1494
1495         if( uniRemoteName.Buffer[ (uniRemoteName.Length/sizeof( WCHAR)) - 1] == L'\\')
1496         {
1497
1498             uniRemoteName.Length -= sizeof( WCHAR);
1499
1500             uniFullName.Length -= sizeof( WCHAR);
1501         }
1502
1503         AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1504                       AFS_TRACE_LEVEL_VERBOSE,
1505                       "AFSGetConnectionInfo Processing name %wZ\n", &uniFullName);
1506
1507         FsRtlDissectName( uniRemoteName,
1508                           &uniServerName,
1509                           &uniRemainingPath);
1510
1511         uniRemoteName = uniRemainingPath;
1512
1513         if( uniRemoteName.Length > 0)
1514         {
1515
1516             FsRtlDissectName( uniRemoteName,
1517                               &uniShareName,
1518                               &uniRemainingPath);
1519         }
1520
1521         if( RtlCompareUnicodeString( &uniServerName,
1522                                      &AFSServerName,
1523                                      TRUE) != 0)
1524         {
1525
1526             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1527         }
1528
1529         if ( uniRemainingPath.Length > 0 )
1530         {
1531
1532             //
1533             // Add back in the leading \ since it was stripped off above
1534             //
1535
1536             uniRemainingPath.Length += sizeof( WCHAR);
1537             if( uniRemainingPath.Length > uniRemainingPath.MaximumLength)
1538             {
1539                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
1540             }
1541
1542             uniRemainingPath.Buffer--;
1543
1544             uniRemainingPathLocal.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1545                                                                               uniRemainingPath.Length,
1546                                                                               AFS_NETWORK_PROVIDER_5_TAG);
1547
1548             if( uniRemainingPathLocal.Buffer == NULL)
1549             {
1550
1551                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1552                               AFS_TRACE_LEVEL_VERBOSE,
1553                               "AFSGetConnectionInfo INSUFFICIENT_RESOURCES\n");
1554
1555                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1556             }
1557
1558             uniRemainingPathLocal.MaximumLength = uniRemainingPath.Length;
1559             uniRemainingPathLocal.Length = uniRemainingPath.Length;
1560
1561             RtlCopyMemory( uniRemainingPathLocal.Buffer,
1562                            uniRemainingPath.Buffer,
1563                            uniRemainingPath.Length);
1564         }
1565
1566         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1567                       AFS_TRACE_LEVEL_VERBOSE,
1568                       "AFSGetConnectionInfo Acquiring AFSProviderListLock lock %08lX SHARED %08lX\n",
1569                       &pRDRDevExt->Specific.RDR.ProviderListLock,
1570                       PsGetCurrentThread());
1571
1572         AFSAcquireShared( &pRDRDevExt->Specific.RDR.ProviderListLock,
1573                           TRUE);
1574
1575         //
1576         // If this is the server then return information about the
1577         // server entry
1578         //
1579
1580         if( uniShareName.Length == 0 &&
1581             RtlCompareUnicodeString( &uniServerName,
1582                                      &AFSServerName,
1583                                      TRUE) == 0)
1584         {
1585
1586             pConnection = pRDRDevExt->Specific.RDR.ProviderEnumerationList;
1587         }
1588         else
1589         {
1590
1591             //
1592             // See if we can locate it on our connection list
1593             //
1594
1595             pConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
1596
1597             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1598                           AFS_TRACE_LEVEL_VERBOSE,
1599                           "AFSGetConnectionInfo Searching for full name %wZ\n", &uniFullName);
1600
1601             while( pConnection != NULL)
1602             {
1603
1604                 if( usMaxNameLen < pConnection->RemoteName.Length &&
1605                     pConnection->RemoteName.Length <= uniFullName.Length)
1606                 {
1607
1608                     usNameLen = uniFullName.Length;
1609
1610                     uniFullName.Length = pConnection->RemoteName.Length;
1611
1612                     if( pConnection->AuthenticationId.QuadPart == ConnectCB->AuthenticationId.QuadPart &&
1613                         RtlCompareUnicodeString( &uniFullName,
1614                                                  &pConnection->RemoteName,
1615                                                  TRUE) == 0)
1616                     {
1617
1618                         usMaxNameLen = pConnection->RemoteName.Length;
1619
1620                         pBestMatch = pConnection;
1621
1622                         AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1623                                       AFS_TRACE_LEVEL_VERBOSE,
1624                                       "AFSGetConnectionInfo Found match for %wZ\n", &pConnection->RemoteName);
1625                     }
1626
1627                     uniFullName.Length = usNameLen;
1628                 }
1629
1630                 pConnection = pConnection->fLink;
1631             }
1632
1633             pConnection = pBestMatch;
1634
1635             if( pConnection != NULL)
1636             {
1637
1638                 bEnumerationEntry = TRUE;
1639
1640                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1641                               AFS_TRACE_LEVEL_VERBOSE,
1642                               "AFSGetConnectionInfo Using best match for %wZ\n", &pConnection->RemoteName);
1643             }
1644
1645             if( pConnection == NULL)
1646             {
1647
1648                 //
1649                 // Locate the entry for the share
1650                 //
1651
1652                 pConnection = AFSLocateEnumRootEntry( &uniShareName);
1653             }
1654         }
1655
1656         if( pConnection == NULL)
1657         {
1658             UNICODE_STRING uniFullName;
1659             AFSDirEnumEntry *pDirEnumEntry = NULL;
1660
1661             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1662                           AFS_TRACE_LEVEL_VERBOSE,
1663                           "AFSGetConnectionInfo No connection for full name %wZ\n", &uniFullName);
1664
1665             //
1666             // Drop the lock, we will pick it up again later
1667             //
1668
1669             AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1670
1671             //
1672             // OK, ask the CM about this component name
1673             //
1674
1675             ntStatus = AFSEvaluateTargetByName( NULL,
1676                                                 &AFSGlobalRoot->ObjectInformation,
1677                                                 &uniShareName,
1678                                                 &pDirEnumEntry);
1679
1680             if( !NT_SUCCESS( ntStatus))
1681             {
1682
1683                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1684                               AFS_TRACE_LEVEL_VERBOSE,
1685                               "AFSGetConnectionInfo Evaluation Failed share name %wZ\n",
1686                               uniShareName);
1687
1688                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1689
1690             }
1691
1692             //
1693             // Don't need this
1694             //
1695
1696             AFSExFreePool( pDirEnumEntry);
1697
1698             //
1699             // The share name is valid
1700             // Allocate a new node and add it to our list
1701             //
1702             uniFullName.MaximumLength = PAGE_SIZE;
1703             uniFullName.Length = 0;
1704
1705             uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1706                                                                     uniFullName.MaximumLength,
1707                                                                     AFS_NETWORK_PROVIDER_6_TAG);
1708
1709             if( uniFullName.Buffer == NULL)
1710             {
1711
1712                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1713                               AFS_TRACE_LEVEL_VERBOSE,
1714                               "AFSGetConnectionInfo INSUFFICIENT_RESOURCES\n");
1715
1716                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1717             }
1718
1719             uniFullName.Buffer[ 0] = L'\\';
1720             uniFullName.Buffer[ 1] = L'\\';
1721
1722             uniFullName.Length = 2 * sizeof( WCHAR);
1723
1724             RtlCopyMemory( &uniFullName.Buffer[ 2],
1725                            AFSServerName.Buffer,
1726                            AFSServerName.Length);
1727
1728             uniFullName.Length += AFSServerName.Length;
1729
1730             uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)] = L'\\';
1731
1732             uniFullName.Length += sizeof( WCHAR);
1733
1734             RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
1735                            uniShareName.Buffer,
1736                            uniShareName.Length);
1737
1738             uniFullName.Length += uniShareName.Length;
1739
1740             AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
1741                             TRUE);
1742
1743             ntStatus = AFSAddConnectionEx( &uniFullName,
1744                                            RESOURCEDISPLAYTYPE_SHARE,
1745                                            0);
1746
1747             AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
1748
1749             AFSExFreePool( uniFullName.Buffer);
1750
1751             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1752                           AFS_TRACE_LEVEL_VERBOSE,
1753                           "AFSGetConnectionInfo Acquiring AFSProviderListLock lock %08lX SHARED %08lX\n",
1754                           &pRDRDevExt->Specific.RDR.ProviderListLock,
1755                           PsGetCurrentThread());
1756
1757             AFSAcquireShared( &pRDRDevExt->Specific.RDR.ProviderListLock,
1758                               TRUE);
1759
1760             if ( NT_SUCCESS( ntStatus) )
1761             {
1762                 //
1763                 // Once again, locate the entry for the share we just created
1764                 //
1765
1766                 pConnection = AFSLocateEnumRootEntry( &uniShareName);
1767             }
1768
1769         }
1770
1771         if( pConnection == NULL)
1772         {
1773
1774             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1775                           AFS_TRACE_LEVEL_ERROR,
1776                           "AFSGetConnectionInfo Failed to locate entry for full name %wZ\n", &uniFullName);
1777
1778             AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1779
1780             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1781         }
1782
1783         //
1784         // Fill in the returned connection info block
1785         //
1786
1787         if( BufferLength < (ULONG)FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1788                                                 pConnection->RemoteName.Length +
1789                                                 pConnection->Comment.Length +
1790                                                 uniRemainingPath.Length)
1791         {
1792
1793             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1794                           AFS_TRACE_LEVEL_VERBOSE,
1795                           "AFSGetConnectionInfo Buffer too small for full name %wZ\n",
1796                           &uniFullName);
1797
1798             AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1799
1800             try_return( ntStatus = STATUS_BUFFER_OVERFLOW);
1801         }
1802
1803         AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1804                       AFS_TRACE_LEVEL_VERBOSE,
1805                       "AFSGetConnectionInfo Returning entry Scope %08lX partial name %wZ full name %wZ\n",
1806                       pConnection->Scope, &pConnection->RemoteName, &uniFullName);
1807
1808         ConnectCB->RemoteNameLength = pConnection->RemoteName.Length;
1809
1810         if( !bEnumerationEntry)
1811         {
1812
1813             RtlCopyMemory( ConnectCB->RemoteName,
1814                            uniFullName.Buffer,
1815                            pConnection->RemoteName.Length);
1816         }
1817         else
1818         {
1819
1820             RtlCopyMemory( ConnectCB->RemoteName,
1821                            pConnection->RemoteName.Buffer,
1822                            pConnection->RemoteName.Length);
1823         }
1824
1825         ConnectCB->LocalName = pConnection->LocalName;
1826
1827         ConnectCB->Type = pConnection->Type;
1828
1829         ConnectCB->Scope = pConnection->Scope;
1830
1831         ConnectCB->DisplayType = pConnection->DisplayType;
1832
1833         ConnectCB->Usage = pConnection->Usage;
1834
1835         ConnectCB->CommentLength = pConnection->Comment.Length;
1836
1837         ConnectCB->RemainingPathLength = uniRemainingPathLocal.Length;
1838
1839         AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
1840                       AFS_TRACE_LEVEL_VERBOSE,
1841                       "AFSGetConnectionInfo Returning lengths: remote %u comment %u remaining %u\n",
1842                       ConnectCB->RemoteNameLength,
1843                       ConnectCB->CommentLength,
1844                       ConnectCB->RemainingPathLength);
1845
1846         if( ConnectCB->CommentLength > 0)
1847         {
1848
1849             ConnectCB->CommentOffset = (ULONG)(FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1850                                                              ConnectCB->RemoteNameLength);
1851
1852             RtlCopyMemory( (void *)((char *)ConnectCB + ConnectCB->CommentOffset),
1853                            pConnection->Comment.Buffer,
1854                            ConnectCB->CommentLength);
1855         }
1856
1857         if ( ConnectCB->RemainingPathLength > 0 )
1858         {
1859
1860             ConnectCB->RemainingPathOffset = (ULONG)(FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1861                                                                    ConnectCB->RemoteNameLength +
1862                                                                    ConnectCB->CommentLength);
1863
1864             RtlCopyMemory( (void *)((char *)ConnectCB + ConnectCB->RemainingPathOffset),
1865                            uniRemainingPathLocal.Buffer,
1866                            uniRemainingPathLocal.Length);
1867         }
1868
1869         *ReturnOutputBufferLength = FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
1870                                                   ConnectCB->RemoteNameLength +
1871                                                   ConnectCB->CommentLength +
1872                                                   ConnectCB->RemainingPathLength;
1873
1874         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1875
1876 try_exit:
1877
1878         if ( uniRemainingPathLocal.Buffer )
1879         {
1880
1881             AFSExFreePool( uniRemainingPathLocal.Buffer);
1882         }
1883     }
1884
1885     return ntStatus;
1886 }
1887
1888 BOOLEAN
1889 AFSIsDriveMapped( IN WCHAR DriveMapping)
1890 {
1891
1892     BOOLEAN bDriveMapped = FALSE;
1893     AFSProviderConnectionCB *pConnection = NULL;
1894     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1895
1896     __Enter
1897     {
1898
1899         AFSAcquireShared( &pRDRDevExt->Specific.RDR.ProviderListLock,
1900                           TRUE);
1901
1902         pConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList;
1903
1904         while( pConnection != NULL)
1905         {
1906
1907             if( pConnection->LocalName != L'\0' &&
1908                 RtlUpcaseUnicodeChar( pConnection->LocalName) == RtlUpcaseUnicodeChar( DriveMapping))
1909             {
1910
1911                 bDriveMapped = TRUE;
1912
1913                 break;
1914             }
1915
1916             pConnection = pConnection->fLink;
1917         }
1918
1919         AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock);
1920     }
1921
1922     return bDriveMapped;
1923 }