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