xref: /reactos/dll/np/nfs/nfs41_np.c (revision e470b583)
1 /* NFSv4.1 client for Windows
2  * Copyright © 2012 The Regents of the University of Michigan
3  *
4  * Olga Kornievskaia <aglo@umich.edu>
5  * Casey Bodley <cbodley@umich.edu>
6  *
7  * This library is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by
9  * the Free Software Foundation; either version 2.1 of the License, or (at
10  * your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful, but
13  * without any warranty; without even the implied warranty of merchantability
14  * or fitness for a particular purpose.  See the GNU Lesser General Public
15  * License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  */
21 
22 #include <windows.h>
23 #include <npapi.h>
24 #include <devioctl.h>
25 #include <strsafe.h>
26 
27 #include "nfs41_driver.h"
28 #include "nfs41_np.h"
29 #include "options.h"
30 
31 #include <pseh/pseh2.h>
32 
33 #ifdef DBG
34 #define DbgP(_x_) NFS41DbgPrint _x_
35 #else
36 #define DbgP(_x_)
37 #endif
38 #define TRACE_TAG   L"[NFS41_NP]"
39 #define WNNC_DRIVER( major, minor ) ( major * 0x00010000 + minor )
40 
41 
NFS41DbgPrint(__in LPTSTR Format,...)42 ULONG _cdecl NFS41DbgPrint( __in LPTSTR Format, ... )
43 {
44     ULONG rc = 0;
45     TCHAR szbuffer[256];
46 
47     va_list marker;
48     va_start( marker, Format );
49     {
50 
51         //StringCchVPrintfW( szbuffer, 127, Format, marker );
52         StringCchVPrintfW( szbuffer, 256, Format, marker );
53         szbuffer[255] = (TCHAR)0;
54         OutputDebugString( TRACE_TAG );
55         OutputDebugString( szbuffer );
56     }
57 
58     return rc;
59 }
60 
filter(unsigned int code)61 int filter(unsigned int code)
62 {
63     DbgP((L"####Got exception %u\n", code));
64     return EXCEPTION_CONTINUE_SEARCH;
65 }
66 
67 DWORD
OpenSharedMemory(PHANDLE phMutex,PHANDLE phMemory,PVOID * pMemory)68 OpenSharedMemory(
69     PHANDLE phMutex,
70     PHANDLE phMemory,
71     PVOID   *pMemory)
72 /*++
73 
74 Routine Description:
75 
76     This routine opens the shared memory for exclusive manipulation
77 
78 Arguments:
79 
80     phMutex - the mutex handle
81 
82     phMemory - the memory handle
83 
84     pMemory - a ptr. to the shared memory which is set if successful
85 
86 Return Value:
87 
88     WN_SUCCESS -- if successful
89 
90 --*/
91 {
92     DWORD dwStatus;
93 
94     *phMutex = 0;
95     *phMemory = 0;
96     *pMemory = NULL;
97 
98     *phMutex = CreateMutex(NULL, FALSE, TEXT(NFS41NP_MUTEX_NAME));
99     if (*phMutex == NULL)
100     {
101         dwStatus = GetLastError();
102         DbgP((TEXT("OpenSharedMemory:  OpenMutex failed\n")));
103         goto OpenSharedMemoryAbort1;
104     }
105 
106     WaitForSingleObject(*phMutex, INFINITE);
107 
108     *phMemory = OpenFileMapping(FILE_MAP_WRITE,
109                                 FALSE,
110                                 TEXT(NFS41_USER_SHARED_MEMORY_NAME));
111     if (*phMemory == NULL)
112     {
113         dwStatus = GetLastError();
114         DbgP((TEXT("OpenSharedMemory:  OpenFileMapping failed\n")));
115         goto OpenSharedMemoryAbort2;
116     }
117 
118     *pMemory = MapViewOfFile(*phMemory, FILE_MAP_WRITE, 0, 0, 0);
119     if (*pMemory == NULL)
120     {
121         dwStatus = GetLastError();
122         DbgP((TEXT("OpenSharedMemory:  MapViewOfFile failed\n")));
123         goto OpenSharedMemoryAbort3;
124     }
125 
126     return ERROR_SUCCESS;
127 
128 OpenSharedMemoryAbort3:
129     CloseHandle(*phMemory);
130 
131 OpenSharedMemoryAbort2:
132     ReleaseMutex(*phMutex);
133     CloseHandle(*phMutex);
134     *phMutex = NULL;
135 
136 OpenSharedMemoryAbort1:
137     DbgP((TEXT("OpenSharedMemory: return dwStatus: %d\n"), dwStatus));
138 
139     return dwStatus;
140 }
141 
142 VOID
CloseSharedMemory(PHANDLE hMutex,PHANDLE hMemory,PVOID * pMemory)143 CloseSharedMemory(
144     PHANDLE hMutex,
145     PHANDLE hMemory,
146     PVOID   *pMemory)
147 /*++
148 
149 Routine Description:
150 
151     This routine relinquishes control of the shared memory after exclusive
152     manipulation
153 
154 Arguments:
155 
156     hMutex - the mutex handle
157 
158     hMemory  - the memory handle
159 
160     pMemory - a ptr. to the shared memory which is set if successful
161 
162 Return Value:
163 
164 --*/
165 {
166     if (*pMemory)
167     {
168         UnmapViewOfFile(*pMemory);
169         *pMemory = NULL;
170     }
171     if (*hMemory)
172     {
173         CloseHandle(*hMemory);
174         *hMemory = 0;
175     }
176     if (*hMutex)
177     {
178         if (ReleaseMutex(*hMutex) == FALSE)
179         {
180             DbgP((TEXT("CloseSharedMemory: ReleaseMutex error: %d\n"), GetLastError()));
181         }
182         CloseHandle(*hMutex);
183         *hMutex = 0;
184     }
185 }
186 
StoreConnectionInfo(IN LPCWSTR LocalName,IN LPCWSTR ConnectionName,IN USHORT ConnectionNameLength,IN LPNETRESOURCE lpNetResource)187 static DWORD StoreConnectionInfo(
188     IN LPCWSTR LocalName,
189     IN LPCWSTR ConnectionName,
190     IN USHORT ConnectionNameLength,
191     IN LPNETRESOURCE lpNetResource)
192 {
193     DWORD status;
194     HANDLE hMutex, hMemory;
195     PNFS41NP_SHARED_MEMORY pSharedMemory;
196     PNFS41NP_NETRESOURCE pNfs41NetResource;
197     INT Index;
198     BOOLEAN FreeEntryFound = FALSE;
199 
200 #ifdef __REACTOS__
201     status = OpenSharedMemory(&hMutex, &hMemory, (PVOID *)&pSharedMemory);
202 #else
203     status = OpenSharedMemory(&hMutex, &hMemory, &(PVOID)pSharedMemory);
204 #endif
205     if (status)
206         goto out;
207 
208     DbgP((TEXT("StoreConnectionInfo: NextIndex %d, NumResources %d\n"),
209         pSharedMemory->NextAvailableIndex,
210         pSharedMemory->NumberOfResourcesInUse));
211 
212     for (Index = 0; Index < pSharedMemory->NextAvailableIndex; Index++)
213     {
214         if (!pSharedMemory->NetResources[Index].InUse)
215         {
216             FreeEntryFound = TRUE;
217             DbgP((TEXT("Reusing existing index %d\n"), Index));
218             break;
219         }
220     }
221 
222     if (!FreeEntryFound)
223     {
224         if (pSharedMemory->NextAvailableIndex >= NFS41NP_MAX_DEVICES) {
225             status = WN_NO_MORE_DEVICES;
226             goto out_close;
227         }
228         Index = pSharedMemory->NextAvailableIndex++;
229         DbgP((TEXT("Using new index %d\n"), Index));
230     }
231 
232     pSharedMemory->NumberOfResourcesInUse += 1;
233 
234     pNfs41NetResource = &pSharedMemory->NetResources[Index];
235 
236     pNfs41NetResource->InUse                = TRUE;
237     pNfs41NetResource->dwScope              = lpNetResource->dwScope;
238     pNfs41NetResource->dwType               = lpNetResource->dwType;
239     pNfs41NetResource->dwDisplayType        = lpNetResource->dwDisplayType;
240     pNfs41NetResource->dwUsage              = RESOURCEUSAGE_CONNECTABLE;
241     pNfs41NetResource->LocalNameLength      = (USHORT)(wcslen(LocalName) + 1) * sizeof(WCHAR);
242     pNfs41NetResource->RemoteNameLength     = (USHORT)(wcslen(lpNetResource->lpRemoteName) + 1) * sizeof(WCHAR);
243     pNfs41NetResource->ConnectionNameLength = ConnectionNameLength;
244 
245     StringCchCopy(pNfs41NetResource->LocalName,
246         pNfs41NetResource->LocalNameLength,
247         LocalName);
248     StringCchCopy(pNfs41NetResource->RemoteName,
249         pNfs41NetResource->RemoteNameLength,
250         lpNetResource->lpRemoteName);
251     StringCchCopy(pNfs41NetResource->ConnectionName,
252         pNfs41NetResource->ConnectionNameLength,
253         ConnectionName);
254 
255     // TODO: copy mount options -cbodley
256 
257 out_close:
258 #ifdef __REACTOS__
259     CloseSharedMemory(&hMutex, &hMemory, (PVOID *)&pSharedMemory);
260 #else
261     CloseSharedMemory(&hMutex, &hMemory, &(PVOID)pSharedMemory);
262 #endif
263 out:
264     return status;
265 }
266 
267 ULONG
SendTo_NFS41Driver(IN ULONG IoctlCode,IN PVOID InputDataBuf,IN ULONG InputDataLen,IN PVOID OutputDataBuf,IN PULONG pOutputDataLen)268 SendTo_NFS41Driver(
269     IN ULONG            IoctlCode,
270     IN PVOID            InputDataBuf,
271     IN ULONG            InputDataLen,
272     IN PVOID            OutputDataBuf,
273     IN PULONG           pOutputDataLen)
274 {
275     HANDLE  DeviceHandle;       // The mini rdr device handle
276     BOOL    rc = FALSE;
277     ULONG   Status;
278 
279     Status = WN_SUCCESS;
280     DbgP((L"[aglo] calling CreateFile\n"));
281     DeviceHandle = CreateFile(
282         NFS41_USER_DEVICE_NAME,
283         GENERIC_READ | GENERIC_WRITE,
284         FILE_SHARE_READ | FILE_SHARE_WRITE,
285         (LPSECURITY_ATTRIBUTES)NULL,
286         OPEN_EXISTING,
287         0,
288         (HANDLE) NULL );
289 
290     DbgP((L"[aglo] after CreateFile Device Handle\n"));
291     if ( INVALID_HANDLE_VALUE != DeviceHandle )
292     {
293         _SEH2_TRY {
294         DbgP((L"[aglo] calling DeviceIoControl\n"));
295         rc = DeviceIoControl(
296             DeviceHandle,
297             IoctlCode,
298             InputDataBuf,
299             InputDataLen,
300             OutputDataBuf,
301             *pOutputDataLen,
302             pOutputDataLen,
303             NULL );
304         } _SEH2_EXCEPT(_SEH2_GetExceptionCode()) {
305             DbgP((L"#### In except\n"));
306         } _SEH2_END;
307         DbgP((L"[aglo] returned from DeviceIoControl %08lx\n", rc));
308             if ( !rc )
309             {
310                 DbgP((L"[aglo] SendTo_NFS41Driver: returning error from DeviceIoctl\n"));
311                 Status = GetLastError( );
312             }
313             else
314             {
315                 DbgP((L"[aglo] SendTo_NFS41Driver: The DeviceIoctl call succeded\n"));
316             }
317             CloseHandle(DeviceHandle);
318     }
319     else
320     {
321         Status = GetLastError( );
322         DbgP((L"[aglo] SendTo_NFS41Driver: error %08lx opening device \n", Status));
323     }
324     DbgP((L"[aglo] returned from SendTo_NFS41Driver %08lx\n", Status));
325     return Status;
326 }
327 
328 DWORD APIENTRY
NPGetCaps(DWORD nIndex)329 NPGetCaps(
330     DWORD nIndex )
331 {
332    DWORD rc = 0;
333 
334 #ifndef __REACTOS__
335     DbgP(( L"[aglo] GetNetCaps %d\n", nIndex ));
336 #endif
337     switch ( nIndex )
338     {
339         case WNNC_SPEC_VERSION:
340             rc = WNNC_SPEC_VERSION51;
341             break;
342 
343         case WNNC_NET_TYPE:
344             rc = WNNC_NET_RDR2SAMPLE;
345             break;
346 
347         case WNNC_DRIVER_VERSION:
348             rc = WNNC_DRIVER(1, 0);
349             break;
350 
351         case WNNC_CONNECTION:
352             rc = WNNC_CON_GETCONNECTIONS |
353                  WNNC_CON_CANCELCONNECTION |
354                  WNNC_CON_ADDCONNECTION |
355                  WNNC_CON_ADDCONNECTION3;
356             break;
357 
358         case WNNC_ENUMERATION:
359             rc = WNNC_ENUM_LOCAL;
360             break;
361 
362         case WNNC_START:
363             rc = 1;
364             break;
365 
366         case WNNC_USER:
367         case WNNC_DIALOG:
368         case WNNC_ADMIN:
369         default:
370             rc = 0;
371             break;
372     }
373 
374     return rc;
375 }
376 
377 DWORD APIENTRY
NPLogonNotify(__in PLUID lpLogonId,__in PCWSTR lpAuthentInfoType,__in PVOID lpAuthentInfo,__in PCWSTR lpPreviousAuthentInfoType,__in PVOID lpPreviousAuthentInfo,__in PWSTR lpStationName,__in PVOID StationHandle,__out PWSTR * lpLogonScript)378 NPLogonNotify(
379     __in PLUID   lpLogonId,
380     __in PCWSTR lpAuthentInfoType,
381     __in PVOID  lpAuthentInfo,
382     __in PCWSTR lpPreviousAuthentInfoType,
383     __in PVOID  lpPreviousAuthentInfo,
384     __in PWSTR  lpStationName,
385     __in PVOID  StationHandle,
386     __out PWSTR  *lpLogonScript)
387 {
388     *lpLogonScript = NULL;
389     DbgP(( L"[aglo] NPLogonNotify: returning WN_SUCCESS\n" ));
390     return WN_SUCCESS;
391 }
392 
393 DWORD APIENTRY
NPPasswordChangeNotify(__in LPCWSTR lpAuthentInfoType,__in LPVOID lpAuthentInfo,__in LPCWSTR lpPreviousAuthentInfoType,__in LPVOID lpPreviousAuthentInfo,__in LPWSTR lpStationName,LPVOID StationHandle,DWORD dwChangeInfo)394 NPPasswordChangeNotify (
395     __in LPCWSTR lpAuthentInfoType,
396     __in LPVOID  lpAuthentInfo,
397     __in LPCWSTR lpPreviousAuthentInfoType,
398     __in LPVOID  lpPreviousAuthentInfo,
399     __in LPWSTR  lpStationName,
400     LPVOID  StationHandle,
401     DWORD   dwChangeInfo )
402 {
403     DbgP(( L"[aglo] NPPasswordChangeNotify: WN_NOT_SUPPORTED\n" ));
404     SetLastError( WN_NOT_SUPPORTED );
405     return WN_NOT_SUPPORTED;
406 }
407 
408 #ifdef __REACTOS__
409 DWORD APIENTRY
410 NPAddConnection3(
411     __in HWND           hwndOwner,
412     __in LPNETRESOURCE  lpNetResource,
413     __in_opt LPWSTR     lpPassword,
414     __in_opt LPWSTR     lpUserName,
415     __in DWORD          dwFlags);
416 #endif
417 
418 DWORD APIENTRY
NPAddConnection(__in LPNETRESOURCE lpNetResource,__in_opt LPWSTR lpPassword,__in_opt LPWSTR lpUserName)419 NPAddConnection(
420     __in LPNETRESOURCE   lpNetResource,
421     __in_opt LPWSTR      lpPassword,
422     __in_opt LPWSTR      lpUserName )
423 {
424     return NPAddConnection3( NULL, lpNetResource, lpPassword, lpUserName, 0 );
425 }
426 
427 DWORD APIENTRY
NPAddConnection3(__in HWND hwndOwner,__in LPNETRESOURCE lpNetResource,__in_opt LPWSTR lpPassword,__in_opt LPWSTR lpUserName,__in DWORD dwFlags)428 NPAddConnection3(
429     __in HWND           hwndOwner,
430     __in LPNETRESOURCE  lpNetResource,
431     __in_opt LPWSTR     lpPassword,
432     __in_opt LPWSTR     lpUserName,
433     __in DWORD          dwFlags)
434 {
435     DWORD   Status;
436     WCHAR   wszScratch[128];
437     WCHAR   LocalName[3];
438     DWORD   CopyBytes = 0;
439     CONNECTION_INFO Connection;
440     LPWSTR  ConnectionName;
441     WCHAR ServerName[MAX_PATH];
442     PWCHAR p;
443     DWORD i;
444 
445     DbgP(( L"[aglo] NPAddConnection3('%s', '%s')\n",
446         lpNetResource->lpLocalName, lpNetResource->lpRemoteName ));
447     DbgP(( L"[aglo] username = '%s', passwd = '%s'\n", lpUserName, lpPassword));
448 
449     Status = InitializeConnectionInfo(&Connection,
450         (PMOUNT_OPTION_BUFFER)lpNetResource->lpComment,
451         &ConnectionName);
452     if (Status)  {
453         DbgP(( L"InitializeConnectionInfo failed with %d\n", Status ));
454         goto out;
455     }
456 
457     //  \device\miniredirector\;<DriveLetter>:\Server\Share
458 
459     // local name, must start with "X:"
460     if (lstrlen(lpNetResource->lpLocalName) < 2 ||
461         lpNetResource->lpLocalName[1] != L':') {
462         Status = WN_BAD_LOCALNAME;
463         goto out;
464     }
465 
466     LocalName[0] = (WCHAR) toupper(lpNetResource->lpLocalName[0]);
467     LocalName[1] = L':';
468     LocalName[2] = L'\0';
469     StringCchCopyW( ConnectionName, MAX_PATH, NFS41_DEVICE_NAME );
470     StringCchCatW( ConnectionName, MAX_PATH, L"\\;" );
471     StringCchCatW( ConnectionName, MAX_PATH, LocalName );
472 
473     // remote name, must start with "\\"
474     if (lpNetResource->lpRemoteName[0] == L'\0' ||
475         lpNetResource->lpRemoteName[0] != L'\\' ||
476         lpNetResource->lpRemoteName[1] != L'\\') {
477         Status = WN_BAD_NETNAME;
478         goto out;
479     }
480 
481     /* note: remotename comes as \\server but we need to add \server thus +1 pointer */
482     p = lpNetResource->lpRemoteName + 1;
483     ServerName[0] = L'\\';
484     i = 1;
485     for(;;) {
486         /* convert servername ending unix slash to windows slash */
487         if (p[i] == L'/')
488             p[i] = L'\\';
489         /* deal with servername ending with any slash */
490         if (p[i] == L'\0')
491             p[i] = L'\\';
492         ServerName[i] = p[i];
493         if (p[i] == L'\\') break;
494         i++;
495     }
496     ServerName[i] = L'\0';
497     StringCchCatW( ConnectionName, MAX_PATH, ServerName);
498     /* insert the "nfs4" in between the server name and the path,
499      * just to make sure all calls to our driver come thru this */
500     StringCchCatW( ConnectionName, MAX_PATH, L"\\nfs4" );
501 
502 #ifdef CONVERT_2_UNIX_SLASHES
503     /* convert all windows slashes to unix slashes */
504     {
505         PWCHAR q = p;
506         DWORD j = 0;
507         for(;;) {
508             if(q[j] == L'\0') break;
509             if (q[j] == L'\\') q[j] = L'/';
510             j++;
511         }
512     }
513 #else
514     /* convert all unix slashes to windows slashes */
515     {
516         PWCHAR q = p;
517         DWORD j = 0;
518         for(;;) {
519             if(q[j] == L'\0') break;
520             if (q[j] == L'/') q[j] = L'\\';
521             j++;
522         }
523     }
524 #endif
525     StringCchCatW( ConnectionName, MAX_PATH, &p[i]);
526     DbgP(( L"[aglo] Full Connect Name: %s\n", ConnectionName ));
527     DbgP(( L"[aglo] Full Connect Name Length: %d %d\n",
528         (wcslen(ConnectionName) + 1) * sizeof(WCHAR),
529         (lstrlen(ConnectionName) + 1) * sizeof(WCHAR)));
530 
531     if ( QueryDosDevice( LocalName, wszScratch, 128 )
532         || GetLastError() != ERROR_FILE_NOT_FOUND) {
533         Status = WN_ALREADY_CONNECTED;
534         goto out;
535     }
536 
537     MarshalConnectionInfo(&Connection);
538 
539     Status = SendTo_NFS41Driver( IOCTL_NFS41_ADDCONN,
540         Connection.Buffer, Connection.BufferSize,
541         NULL, &CopyBytes );
542     if (Status) {
543         DbgP(( L"[aglo] SendTo_NFS41Driver failed with %d\n", Status));
544         goto out;
545     }
546 
547     DbgP(( L"[aglo] calling DefineDosDevice\n"));
548     if ( !DefineDosDevice( DDD_RAW_TARGET_PATH |
549                            DDD_NO_BROADCAST_SYSTEM,
550                            lpNetResource->lpLocalName,
551                            ConnectionName ) ) {
552         Status = GetLastError();
553         DbgP(( L"[aglo] DefineDosDevice failed with %d\n", Status));
554         goto out_delconn;
555     }
556 
557     // The connection was established and the local device mapping
558     // added. Include this in the list of mapped devices.
559     Status = StoreConnectionInfo(LocalName, ConnectionName,
560         Connection.Buffer->NameLength, lpNetResource);
561     if (Status) {
562         DbgP(( L"[aglo] StoreConnectionInfo failed with %d\n", Status));
563         goto out_undefine;
564     }
565 
566 out:
567     FreeConnectionInfo(&Connection);
568     DbgP(( L"[aglo] NPAddConnection3: status %08X\n", Status));
569     return Status;
570 out_undefine:
571     DefineDosDevice(DDD_REMOVE_DEFINITION | DDD_RAW_TARGET_PATH |
572         DDD_EXACT_MATCH_ON_REMOVE, LocalName, ConnectionName);
573 out_delconn:
574     SendTo_NFS41Driver(IOCTL_NFS41_DELCONN, ConnectionName,
575         Connection.Buffer->NameLength, NULL, &CopyBytes);
576     goto out;
577 }
578 
579 DWORD APIENTRY
NPCancelConnection(__in LPWSTR lpName,__in BOOL fForce)580 NPCancelConnection(
581     __in LPWSTR  lpName,
582     __in BOOL    fForce )
583 {
584     DWORD   Status = 0;
585 
586     HANDLE  hMutex, hMemory;
587     PNFS41NP_SHARED_MEMORY  pSharedMemory;
588 
589     DbgP((TEXT("NPCancelConnection\n")));
590     DbgP((TEXT("NPCancelConnection: ConnectionName: %S\n"), lpName));
591 
592     Status = OpenSharedMemory( &hMutex,
593                                &hMemory,
594                                (PVOID)&pSharedMemory);
595 
596     if (Status == WN_SUCCESS)
597     {
598         INT  Index;
599         PNFS41NP_NETRESOURCE pNetResource;
600         Status = WN_NOT_CONNECTED;
601 
602         DbgP((TEXT("NPCancelConnection: NextIndex %d, NumResources %d\n"),
603                     pSharedMemory->NextAvailableIndex,
604                     pSharedMemory->NumberOfResourcesInUse));
605 
606         for (Index = 0; Index < pSharedMemory->NextAvailableIndex; Index++)
607         {
608             pNetResource = &pSharedMemory->NetResources[Index];
609 
610             if (pNetResource->InUse)
611             {
612                 if ( ( (wcslen(lpName) + 1) * sizeof(WCHAR) ==
613                         pNetResource->LocalNameLength)
614                         && ( !wcscmp(lpName, pNetResource->LocalName) ))
615                 {
616                     ULONG CopyBytes;
617 
618                     DbgP((TEXT("NPCancelConnection: Connection Found:\n")));
619 
620                     CopyBytes = 0;
621 
622                     Status = SendTo_NFS41Driver( IOCTL_NFS41_DELCONN,
623                                 pNetResource->ConnectionName,
624                                 pNetResource->ConnectionNameLength,
625                                 NULL,
626                                 &CopyBytes );
627 
628                     if (Status != WN_SUCCESS)
629                     {
630                         DbgP((TEXT("NPCancelConnection: SendToMiniRdr returned Status %lx\n"),Status));
631                         break;
632                     }
633 
634                     if (DefineDosDevice(DDD_REMOVE_DEFINITION | DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE,
635                             lpName,
636                             pNetResource->ConnectionName) == FALSE)
637                     {
638                         DbgP((TEXT("RemoveDosDevice:  DefineDosDevice error: %d\n"), GetLastError()));
639                         Status = GetLastError();
640                     }
641                     else
642                     {
643                         pNetResource->InUse = FALSE;
644                         pSharedMemory->NumberOfResourcesInUse--;
645 
646                         if (Index+1 == pSharedMemory->NextAvailableIndex)
647                             pSharedMemory->NextAvailableIndex--;
648                     }
649                     break;
650                 }
651 
652                 DbgP((TEXT("NPCancelConnection: Name %S EntryName %S\n"),
653                             lpName,pNetResource->LocalName));
654 #ifndef __REACTOS__
655                 DbgP((TEXT("NPCancelConnection: Name Length %d Entry Name Length %d\n"),
656                            pNetResource->LocalNameLength,pNetResource->LocalName));
657 #else
658                 DbgP((TEXT("NPCancelConnection: Name Length %d Entry Name Length %d\n"),
659                            (wcslen(lpName) + 1) * sizeof(WCHAR), pNetResource->LocalNameLength));
660 #endif
661 
662             }
663         }
664 
665         CloseSharedMemory( &hMutex,
666                            &hMemory,
667                           (PVOID)&pSharedMemory);
668     }
669 
670     return Status;
671 }
672 
673 DWORD APIENTRY
NPGetConnection(__in LPWSTR lpLocalName,__out_bcount (* lpBufferSize)LPWSTR lpRemoteName,__inout LPDWORD lpBufferSize)674 NPGetConnection(
675     __in LPWSTR  lpLocalName,
676     __out_bcount(*lpBufferSize) LPWSTR  lpRemoteName,
677     __inout LPDWORD lpBufferSize )
678 {
679     DWORD   Status = 0;
680 
681     HANDLE  hMutex, hMemory;
682     PNFS41NP_SHARED_MEMORY  pSharedMemory;
683 
684     Status = OpenSharedMemory( &hMutex,
685                                &hMemory,
686                                (PVOID)&pSharedMemory);
687 
688     if (Status == WN_SUCCESS)
689     {
690         INT  Index;
691         PNFS41NP_NETRESOURCE pNetResource;
692         Status = WN_NOT_CONNECTED;
693 
694         for (Index = 0; Index < pSharedMemory->NextAvailableIndex; Index++)
695         {
696             pNetResource = &pSharedMemory->NetResources[Index];
697 
698             if (pNetResource->InUse)
699             {
700                 if ( ( (wcslen(lpLocalName) + 1) * sizeof(WCHAR) ==
701                         pNetResource->LocalNameLength)
702                         && ( !wcscmp(lpLocalName, pNetResource->LocalName) ))
703                 {
704                     if (*lpBufferSize < pNetResource->RemoteNameLength)
705                     {
706                         *lpBufferSize = pNetResource->RemoteNameLength;
707                         Status = WN_MORE_DATA;
708                     }
709                     else
710                     {
711                         *lpBufferSize = pNetResource->RemoteNameLength;
712                         CopyMemory( lpRemoteName,
713                                     pNetResource->RemoteName,
714                                     pNetResource->RemoteNameLength);
715                         Status = WN_SUCCESS;
716                     }
717                     break;
718                 }
719             }
720         }
721 
722         CloseSharedMemory( &hMutex, &hMemory, (PVOID)&pSharedMemory);
723     }
724 
725     return Status;
726 }
727 
728 DWORD APIENTRY
NPOpenEnum(DWORD dwScope,DWORD dwType,DWORD dwUsage,LPNETRESOURCE lpNetResource,LPHANDLE lphEnum)729 NPOpenEnum(
730     DWORD          dwScope,
731     DWORD          dwType,
732     DWORD          dwUsage,
733     LPNETRESOURCE  lpNetResource,
734     LPHANDLE       lphEnum )
735 {
736     DWORD   Status;
737 
738     DbgP((L"[aglo] NPOpenEnum\n"));
739 
740     *lphEnum = NULL;
741 
742     switch ( dwScope )
743     {
744         case RESOURCE_CONNECTED:
745         {
746             *lphEnum = HeapAlloc( GetProcessHeap( ), HEAP_ZERO_MEMORY, sizeof( ULONG ) );
747 
748             if (*lphEnum )
749             {
750                 Status = WN_SUCCESS;
751             }
752             else
753             {
754                 Status = WN_OUT_OF_MEMORY;
755             }
756             break;
757         }
758         break;
759 
760         case RESOURCE_CONTEXT:
761         default:
762             Status  = WN_NOT_SUPPORTED;
763             break;
764     }
765 
766 
767     DbgP((L"[aglo] NPOpenEnum returning Status %lx\n",Status));
768 
769     return(Status);
770 }
771 
772 DWORD APIENTRY
NPEnumResource(HANDLE hEnum,LPDWORD lpcCount,LPVOID lpBuffer,LPDWORD lpBufferSize)773 NPEnumResource(
774     HANDLE  hEnum,
775     LPDWORD lpcCount,
776     LPVOID  lpBuffer,
777     LPDWORD lpBufferSize)
778 {
779     DWORD           Status = WN_SUCCESS;
780     ULONG           EntriesCopied;
781     LPNETRESOURCE   pNetResource;
782     ULONG           SpaceNeeded = 0;
783     ULONG           SpaceAvailable;
784     PWCHAR          StringZone;
785     HANDLE  hMutex, hMemory;
786     PNFS41NP_SHARED_MEMORY  pSharedMemory;
787     PNFS41NP_NETRESOURCE pNfsNetResource;
788     INT  Index = *(PULONG)hEnum;
789 
790 
791     DbgP((L"[aglo] NPEnumResource\n"));
792 
793     DbgP((L"[aglo] NPEnumResource Count Requested %d\n", *lpcCount));
794 
795     pNetResource = (LPNETRESOURCE) lpBuffer;
796     SpaceAvailable = *lpBufferSize;
797     EntriesCopied = 0;
798     StringZone = (PWCHAR) ((PBYTE)lpBuffer + *lpBufferSize);
799 
800     Status = OpenSharedMemory( &hMutex,
801                                &hMemory,
802                                (PVOID)&pSharedMemory);
803 
804     if ( Status == WN_SUCCESS)
805     {
806         Status = WN_NO_MORE_ENTRIES;
807         for (Index = *(PULONG)hEnum; EntriesCopied < *lpcCount &&
808                 Index < pSharedMemory->NextAvailableIndex; Index++)
809         {
810             pNfsNetResource = &pSharedMemory->NetResources[Index];
811 
812             if (pNfsNetResource->InUse)
813             {
814                 SpaceNeeded  = sizeof( NETRESOURCE );
815                 SpaceNeeded += pNfsNetResource->LocalNameLength;
816                 SpaceNeeded += pNfsNetResource->RemoteNameLength;
817                 SpaceNeeded += 5 * sizeof(WCHAR);               // comment
818                 SpaceNeeded += sizeof(NFS41_PROVIDER_NAME_U);  // provider name
819                 if ( SpaceNeeded > SpaceAvailable )
820                 {
821                     Status = WN_MORE_DATA;
822                     DbgP((L"[aglo] NPEnumResource More Data Needed - %d\n", SpaceNeeded));
823                     *lpBufferSize = SpaceNeeded;
824                     break;
825                 }
826                 else
827                 {
828                     SpaceAvailable -= SpaceNeeded;
829 
830                     pNetResource->dwScope       = pNfsNetResource->dwScope;
831                     pNetResource->dwType        = pNfsNetResource->dwType;
832                     pNetResource->dwDisplayType = pNfsNetResource->dwDisplayType;
833                     pNetResource->dwUsage       = pNfsNetResource->dwUsage;
834 
835                     // setup string area at opposite end of buffer
836                     SpaceNeeded -= sizeof( NETRESOURCE );
837                     StringZone = (PWCHAR)( (PBYTE) StringZone - SpaceNeeded );
838                     // copy local name
839                     StringCchCopy( StringZone,
840                         pNfsNetResource->LocalNameLength,
841                         pNfsNetResource->LocalName );
842                     pNetResource->lpLocalName = StringZone;
843                     StringZone += pNfsNetResource->LocalNameLength/sizeof(WCHAR);
844                     // copy remote name
845                     StringCchCopy( StringZone,
846                         pNfsNetResource->RemoteNameLength,
847                         pNfsNetResource->RemoteName );
848                     pNetResource->lpRemoteName = StringZone;
849                     StringZone += pNfsNetResource->RemoteNameLength/sizeof(WCHAR);
850                     // copy comment
851                     pNetResource->lpComment = StringZone;
852                     *StringZone++ = L'A';
853                     *StringZone++ = L'_';
854                     *StringZone++ = L'O';
855                     *StringZone++ = L'K';
856                     *StringZone++ = L'\0';
857                     // copy provider name
858                     pNetResource->lpProvider = StringZone;
859                     StringCbCopyW( StringZone, sizeof(NFS41_PROVIDER_NAME_U), NFS41_PROVIDER_NAME_U );
860                     StringZone += sizeof(NFS41_PROVIDER_NAME_U)/sizeof(WCHAR);
861                     EntriesCopied++;
862                     // set new bottom of string zone
863                     StringZone = (PWCHAR)( (PBYTE) StringZone - SpaceNeeded );
864                     Status = WN_SUCCESS;
865                 }
866                 pNetResource++;
867             }
868         }
869         CloseSharedMemory( &hMutex, &hMemory, (PVOID*)&pSharedMemory);
870     }
871 
872     *lpcCount = EntriesCopied;
873     *(PULONG) hEnum = Index;
874 
875     DbgP((L"[aglo] NPEnumResource entries returned: %d\n", EntriesCopied));
876 
877     return Status;
878 }
879 
880 DWORD APIENTRY
NPCloseEnum(HANDLE hEnum)881 NPCloseEnum(
882     HANDLE hEnum )
883 {
884     DbgP((L"[aglo] NPCloseEnum\n"));
885     HeapFree( GetProcessHeap( ), 0, (PVOID) hEnum );
886     return WN_SUCCESS;
887 }
888 
889 DWORD APIENTRY
NPGetResourceParent(LPNETRESOURCE lpNetResource,LPVOID lpBuffer,LPDWORD lpBufferSize)890 NPGetResourceParent(
891     LPNETRESOURCE   lpNetResource,
892     LPVOID  lpBuffer,
893     LPDWORD lpBufferSize )
894 {
895     DbgP(( L"[aglo] NPGetResourceParent: WN_NOT_SUPPORTED\n" ));
896     return WN_NOT_SUPPORTED;
897 }
898 
899 DWORD APIENTRY
NPGetResourceInformation(__in LPNETRESOURCE lpNetResource,__out_bcount (* lpBufferSize)LPVOID lpBuffer,__inout LPDWORD lpBufferSize,__deref_out LPWSTR * lplpSystem)900 NPGetResourceInformation(
901     __in LPNETRESOURCE   lpNetResource,
902     __out_bcount(*lpBufferSize) LPVOID  lpBuffer,
903     __inout LPDWORD lpBufferSize,
904     __deref_out LPWSTR *lplpSystem )
905 {
906     DbgP(( L"[aglo] NPGetResourceInformation: WN_NOT_SUPPORTED\n" ));
907     return WN_NOT_SUPPORTED;
908 }
909 
910 DWORD APIENTRY
NPGetUniversalName(LPCWSTR lpLocalPath,DWORD dwInfoLevel,LPVOID lpBuffer,LPDWORD lpBufferSize)911 NPGetUniversalName(
912     LPCWSTR lpLocalPath,
913     DWORD   dwInfoLevel,
914     LPVOID  lpBuffer,
915     LPDWORD lpBufferSize )
916 {
917     DbgP(( L"[aglo] NPGetUniversalName: WN_NOT_SUPPORTED\n" ));
918     return WN_NOT_SUPPORTED;
919 }
920