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