42aa46730d8864330eab2e06707daf5048480015
[reactos.git] / 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 #ifndef __REACTOS__
333 DbgP(( L"[aglo] GetNetCaps %d\n", nIndex ));
334 #endif
335 switch ( nIndex )
336 {
337 case WNNC_SPEC_VERSION:
338 rc = WNNC_SPEC_VERSION51;
339 break;
340
341 case WNNC_NET_TYPE:
342 rc = WNNC_NET_RDR2SAMPLE;
343 break;
344
345 case WNNC_DRIVER_VERSION:
346 rc = WNNC_DRIVER(1, 0);
347 break;
348
349 case WNNC_CONNECTION:
350 rc = WNNC_CON_GETCONNECTIONS |
351 WNNC_CON_CANCELCONNECTION |
352 WNNC_CON_ADDCONNECTION |
353 WNNC_CON_ADDCONNECTION3;
354 break;
355
356 case WNNC_ENUMERATION:
357 rc = WNNC_ENUM_LOCAL;
358 break;
359
360 case WNNC_START:
361 rc = 1;
362 break;
363
364 case WNNC_USER:
365 case WNNC_DIALOG:
366 case WNNC_ADMIN:
367 default:
368 rc = 0;
369 break;
370 }
371
372 return rc;
373 }
374
375 DWORD APIENTRY
376 NPLogonNotify(
377 __in PLUID lpLogonId,
378 __in PCWSTR lpAuthentInfoType,
379 __in PVOID lpAuthentInfo,
380 __in PCWSTR lpPreviousAuthentInfoType,
381 __in PVOID lpPreviousAuthentInfo,
382 __in PWSTR lpStationName,
383 __in PVOID StationHandle,
384 __out PWSTR *lpLogonScript)
385 {
386 *lpLogonScript = NULL;
387 DbgP(( L"[aglo] NPLogonNotify: returning WN_SUCCESS\n" ));
388 return WN_SUCCESS;
389 }
390
391 DWORD APIENTRY
392 NPPasswordChangeNotify (
393 __in LPCWSTR lpAuthentInfoType,
394 __in LPVOID lpAuthentInfo,
395 __in LPCWSTR lpPreviousAuthentInfoType,
396 __in LPVOID lpPreviousAuthentInfo,
397 __in LPWSTR lpStationName,
398 LPVOID StationHandle,
399 DWORD dwChangeInfo )
400 {
401 DbgP(( L"[aglo] NPPasswordChangeNotify: WN_NOT_SUPPORTED\n" ));
402 SetLastError( WN_NOT_SUPPORTED );
403 return WN_NOT_SUPPORTED;
404 }
405
406 #ifdef __REACTOS__
407 DWORD APIENTRY
408 NPAddConnection3(
409 __in HWND hwndOwner,
410 __in LPNETRESOURCE lpNetResource,
411 __in_opt LPWSTR lpPassword,
412 __in_opt LPWSTR lpUserName,
413 __in DWORD dwFlags);
414 #endif
415
416 DWORD APIENTRY
417 NPAddConnection(
418 __in LPNETRESOURCE lpNetResource,
419 __in_opt LPWSTR lpPassword,
420 __in_opt LPWSTR lpUserName )
421 {
422 return NPAddConnection3( NULL, lpNetResource, lpPassword, lpUserName, 0 );
423 }
424
425 DWORD APIENTRY
426 NPAddConnection3(
427 __in HWND hwndOwner,
428 __in LPNETRESOURCE lpNetResource,
429 __in_opt LPWSTR lpPassword,
430 __in_opt LPWSTR lpUserName,
431 __in DWORD dwFlags)
432 {
433 DWORD Status;
434 WCHAR wszScratch[128];
435 WCHAR LocalName[3];
436 DWORD CopyBytes = 0;
437 CONNECTION_INFO Connection;
438 LPWSTR ConnectionName;
439 WCHAR ServerName[MAX_PATH];
440 PWCHAR p;
441 DWORD i;
442
443 DbgP(( L"[aglo] NPAddConnection3('%s', '%s')\n",
444 lpNetResource->lpLocalName, lpNetResource->lpRemoteName ));
445 DbgP(( L"[aglo] username = '%s', passwd = '%s'\n", lpUserName, lpPassword));
446
447 Status = InitializeConnectionInfo(&Connection,
448 (PMOUNT_OPTION_BUFFER)lpNetResource->lpComment,
449 &ConnectionName);
450 if (Status) {
451 DbgP(( L"InitializeConnectionInfo failed with %d\n", Status ));
452 goto out;
453 }
454
455 // \device\miniredirector\;<DriveLetter>:\Server\Share
456
457 // local name, must start with "X:"
458 if (lstrlen(lpNetResource->lpLocalName) < 2 ||
459 lpNetResource->lpLocalName[1] != L':') {
460 Status = WN_BAD_LOCALNAME;
461 goto out;
462 }
463
464 LocalName[0] = (WCHAR) toupper(lpNetResource->lpLocalName[0]);
465 LocalName[1] = L':';
466 LocalName[2] = L'\0';
467 StringCchCopyW( ConnectionName, MAX_PATH, NFS41_DEVICE_NAME );
468 StringCchCatW( ConnectionName, MAX_PATH, L"\\;" );
469 StringCchCatW( ConnectionName, MAX_PATH, LocalName );
470
471 // remote name, must start with "\\"
472 if (lpNetResource->lpRemoteName[0] == L'\0' ||
473 lpNetResource->lpRemoteName[0] != L'\\' ||
474 lpNetResource->lpRemoteName[1] != L'\\') {
475 Status = WN_BAD_NETNAME;
476 goto out;
477 }
478
479 /* note: remotename comes as \\server but we need to add \server thus +1 pointer */
480 p = lpNetResource->lpRemoteName + 1;
481 ServerName[0] = L'\\';
482 i = 1;
483 for(;;) {
484 /* convert servername ending unix slash to windows slash */
485 if (p[i] == L'/')
486 p[i] = L'\\';
487 /* deal with servername ending with any slash */
488 if (p[i] == L'\0')
489 p[i] = L'\\';
490 ServerName[i] = p[i];
491 if (p[i] == L'\\') break;
492 i++;
493 }
494 ServerName[i] = L'\0';
495 StringCchCatW( ConnectionName, MAX_PATH, ServerName);
496 /* insert the "nfs4" in between the server name and the path,
497 * just to make sure all calls to our driver come thru this */
498 StringCchCatW( ConnectionName, MAX_PATH, L"\\nfs4" );
499
500 #ifdef CONVERT_2_UNIX_SLASHES
501 /* convert all windows slashes to unix slashes */
502 {
503 PWCHAR q = p;
504 DWORD j = 0;
505 for(;;) {
506 if(q[j] == L'\0') break;
507 if (q[j] == L'\\') q[j] = L'/';
508 j++;
509 }
510 }
511 #else
512 /* convert all unix slashes to windows slashes */
513 {
514 PWCHAR q = p;
515 DWORD j = 0;
516 for(;;) {
517 if(q[j] == L'\0') break;
518 if (q[j] == L'/') q[j] = L'\\';
519 j++;
520 }
521 }
522 #endif
523 StringCchCatW( ConnectionName, MAX_PATH, &p[i]);
524 DbgP(( L"[aglo] Full Connect Name: %s\n", ConnectionName ));
525 DbgP(( L"[aglo] Full Connect Name Length: %d %d\n",
526 (wcslen(ConnectionName) + 1) * sizeof(WCHAR),
527 (lstrlen(ConnectionName) + 1) * sizeof(WCHAR)));
528
529 if ( QueryDosDevice( LocalName, wszScratch, 128 )
530 || GetLastError() != ERROR_FILE_NOT_FOUND) {
531 Status = WN_ALREADY_CONNECTED;
532 goto out;
533 }
534
535 MarshalConnectionInfo(&Connection);
536
537 Status = SendTo_NFS41Driver( IOCTL_NFS41_ADDCONN,
538 Connection.Buffer, Connection.BufferSize,
539 NULL, &CopyBytes );
540 if (Status) {
541 DbgP(( L"[aglo] SendTo_NFS41Driver failed with %d\n", Status));
542 goto out;
543 }
544
545 DbgP(( L"[aglo] calling DefineDosDevice\n"));
546 if ( !DefineDosDevice( DDD_RAW_TARGET_PATH |
547 DDD_NO_BROADCAST_SYSTEM,
548 lpNetResource->lpLocalName,
549 ConnectionName ) ) {
550 Status = GetLastError();
551 DbgP(( L"[aglo] DefineDosDevice failed with %d\n", Status));
552 goto out_delconn;
553 }
554
555 // The connection was established and the local device mapping
556 // added. Include this in the list of mapped devices.
557 Status = StoreConnectionInfo(LocalName, ConnectionName,
558 Connection.Buffer->NameLength, lpNetResource);
559 if (Status) {
560 DbgP(( L"[aglo] StoreConnectionInfo failed with %d\n", Status));
561 goto out_undefine;
562 }
563
564 out:
565 FreeConnectionInfo(&Connection);
566 DbgP(( L"[aglo] NPAddConnection3: status %08X\n", Status));
567 return Status;
568 out_undefine:
569 DefineDosDevice(DDD_REMOVE_DEFINITION | DDD_RAW_TARGET_PATH |
570 DDD_EXACT_MATCH_ON_REMOVE, LocalName, ConnectionName);
571 out_delconn:
572 SendTo_NFS41Driver(IOCTL_NFS41_DELCONN, ConnectionName,
573 Connection.Buffer->NameLength, NULL, &CopyBytes);
574 goto out;
575 }
576
577 DWORD APIENTRY
578 NPCancelConnection(
579 __in LPWSTR lpName,
580 __in BOOL fForce )
581 {
582 DWORD Status = 0;
583
584 HANDLE hMutex, hMemory;
585 PNFS41NP_SHARED_MEMORY pSharedMemory;
586
587 DbgP((TEXT("NPCancelConnection\n")));
588 DbgP((TEXT("NPCancelConnection: ConnectionName: %S\n"), lpName));
589
590 Status = OpenSharedMemory( &hMutex,
591 &hMemory,
592 (PVOID)&pSharedMemory);
593
594 if (Status == WN_SUCCESS)
595 {
596 INT Index;
597 PNFS41NP_NETRESOURCE pNetResource;
598 Status = WN_NOT_CONNECTED;
599
600 DbgP((TEXT("NPCancelConnection: NextIndex %d, NumResources %d\n"),
601 pSharedMemory->NextAvailableIndex,
602 pSharedMemory->NumberOfResourcesInUse));
603
604 for (Index = 0; Index < pSharedMemory->NextAvailableIndex; Index++)
605 {
606 pNetResource = &pSharedMemory->NetResources[Index];
607
608 if (pNetResource->InUse)
609 {
610 if ( ( (wcslen(lpName) + 1) * sizeof(WCHAR) ==
611 pNetResource->LocalNameLength)
612 && ( !wcscmp(lpName, pNetResource->LocalName) ))
613 {
614 ULONG CopyBytes;
615
616 DbgP((TEXT("NPCancelConnection: Connection Found:\n")));
617
618 CopyBytes = 0;
619
620 Status = SendTo_NFS41Driver( IOCTL_NFS41_DELCONN,
621 pNetResource->ConnectionName,
622 pNetResource->ConnectionNameLength,
623 NULL,
624 &CopyBytes );
625
626 if (Status != WN_SUCCESS)
627 {
628 DbgP((TEXT("NPCancelConnection: SendToMiniRdr returned Status %lx\n"),Status));
629 break;
630 }
631
632 if (DefineDosDevice(DDD_REMOVE_DEFINITION | DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE,
633 lpName,
634 pNetResource->ConnectionName) == FALSE)
635 {
636 DbgP((TEXT("RemoveDosDevice: DefineDosDevice error: %d\n"), GetLastError()));
637 Status = GetLastError();
638 }
639 else
640 {
641 pNetResource->InUse = FALSE;
642 pSharedMemory->NumberOfResourcesInUse--;
643
644 if (Index+1 == pSharedMemory->NextAvailableIndex)
645 pSharedMemory->NextAvailableIndex--;
646 }
647 break;
648 }
649
650 DbgP((TEXT("NPCancelConnection: Name %S EntryName %S\n"),
651 lpName,pNetResource->LocalName));
652 DbgP((TEXT("NPCancelConnection: Name Length %d Entry Name Length %d\n"),
653 #ifndef __REACTOS__
654 pNetResource->LocalNameLength,pNetResource->LocalName));
655 #else
656 (wcslen(lpName) + 1) * sizeof(WCHAR), pNetResource->LocalNameLength));
657 #endif
658
659 }
660 }
661
662 CloseSharedMemory( &hMutex,
663 &hMemory,
664 (PVOID)&pSharedMemory);
665 }
666
667 return Status;
668 }
669
670 DWORD APIENTRY
671 NPGetConnection(
672 __in LPWSTR lpLocalName,
673 __out_bcount(*lpBufferSize) LPWSTR lpRemoteName,
674 __inout LPDWORD lpBufferSize )
675 {
676 DWORD Status = 0;
677
678 HANDLE hMutex, hMemory;
679 PNFS41NP_SHARED_MEMORY pSharedMemory;
680
681 Status = OpenSharedMemory( &hMutex,
682 &hMemory,
683 (PVOID)&pSharedMemory);
684
685 if (Status == WN_SUCCESS)
686 {
687 INT Index;
688 PNFS41NP_NETRESOURCE pNetResource;
689 Status = WN_NOT_CONNECTED;
690
691 for (Index = 0; Index < pSharedMemory->NextAvailableIndex; Index++)
692 {
693 pNetResource = &pSharedMemory->NetResources[Index];
694
695 if (pNetResource->InUse)
696 {
697 if ( ( (wcslen(lpLocalName) + 1) * sizeof(WCHAR) ==
698 pNetResource->LocalNameLength)
699 && ( !wcscmp(lpLocalName, pNetResource->LocalName) ))
700 {
701 if (*lpBufferSize < pNetResource->RemoteNameLength)
702 {
703 *lpBufferSize = pNetResource->RemoteNameLength;
704 Status = WN_MORE_DATA;
705 }
706 else
707 {
708 *lpBufferSize = pNetResource->RemoteNameLength;
709 CopyMemory( lpRemoteName,
710 pNetResource->RemoteName,
711 pNetResource->RemoteNameLength);
712 Status = WN_SUCCESS;
713 }
714 break;
715 }
716 }
717 }
718
719 CloseSharedMemory( &hMutex, &hMemory, (PVOID)&pSharedMemory);
720 }
721
722 return Status;
723 }
724
725 DWORD APIENTRY
726 NPOpenEnum(
727 DWORD dwScope,
728 DWORD dwType,
729 DWORD dwUsage,
730 LPNETRESOURCE lpNetResource,
731 LPHANDLE lphEnum )
732 {
733 DWORD Status;
734
735 DbgP((L"[aglo] NPOpenEnum\n"));
736
737 *lphEnum = NULL;
738
739 switch ( dwScope )
740 {
741 case RESOURCE_CONNECTED:
742 {
743 *lphEnum = HeapAlloc( GetProcessHeap( ), HEAP_ZERO_MEMORY, sizeof( ULONG ) );
744
745 if (*lphEnum )
746 {
747 Status = WN_SUCCESS;
748 }
749 else
750 {
751 Status = WN_OUT_OF_MEMORY;
752 }
753 break;
754 }
755 break;
756
757 case RESOURCE_CONTEXT:
758 default:
759 Status = WN_NOT_SUPPORTED;
760 break;
761 }
762
763
764 DbgP((L"[aglo] NPOpenEnum returning Status %lx\n",Status));
765
766 return(Status);
767 }
768
769 DWORD APIENTRY
770 NPEnumResource(
771 HANDLE hEnum,
772 LPDWORD lpcCount,
773 LPVOID lpBuffer,
774 LPDWORD lpBufferSize)
775 {
776 DWORD Status = WN_SUCCESS;
777 ULONG EntriesCopied;
778 LPNETRESOURCE pNetResource;
779 ULONG SpaceNeeded = 0;
780 ULONG SpaceAvailable;
781 PWCHAR StringZone;
782 HANDLE hMutex, hMemory;
783 PNFS41NP_SHARED_MEMORY pSharedMemory;
784 PNFS41NP_NETRESOURCE pNfsNetResource;
785 INT Index = *(PULONG)hEnum;
786
787
788 DbgP((L"[aglo] NPEnumResource\n"));
789
790 DbgP((L"[aglo] NPEnumResource Count Requested %d\n", *lpcCount));
791
792 pNetResource = (LPNETRESOURCE) lpBuffer;
793 SpaceAvailable = *lpBufferSize;
794 EntriesCopied = 0;
795 StringZone = (PWCHAR) ((PBYTE)lpBuffer + *lpBufferSize);
796
797 Status = OpenSharedMemory( &hMutex,
798 &hMemory,
799 (PVOID)&pSharedMemory);
800
801 if ( Status == WN_SUCCESS)
802 {
803 Status = WN_NO_MORE_ENTRIES;
804 for (Index = *(PULONG)hEnum; EntriesCopied < *lpcCount &&
805 Index < pSharedMemory->NextAvailableIndex; Index++)
806 {
807 pNfsNetResource = &pSharedMemory->NetResources[Index];
808
809 if (pNfsNetResource->InUse)
810 {
811 SpaceNeeded = sizeof( NETRESOURCE );
812 SpaceNeeded += pNfsNetResource->LocalNameLength;
813 SpaceNeeded += pNfsNetResource->RemoteNameLength;
814 SpaceNeeded += 5 * sizeof(WCHAR); // comment
815 SpaceNeeded += sizeof(NFS41_PROVIDER_NAME_U); // provider name
816 if ( SpaceNeeded > SpaceAvailable )
817 {
818 Status = WN_MORE_DATA;
819 DbgP((L"[aglo] NPEnumResource More Data Needed - %d\n", SpaceNeeded));
820 *lpBufferSize = SpaceNeeded;
821 break;
822 }
823 else
824 {
825 SpaceAvailable -= SpaceNeeded;
826
827 pNetResource->dwScope = pNfsNetResource->dwScope;
828 pNetResource->dwType = pNfsNetResource->dwType;
829 pNetResource->dwDisplayType = pNfsNetResource->dwDisplayType;
830 pNetResource->dwUsage = pNfsNetResource->dwUsage;
831
832 // setup string area at opposite end of buffer
833 SpaceNeeded -= sizeof( NETRESOURCE );
834 StringZone = (PWCHAR)( (PBYTE) StringZone - SpaceNeeded );
835 // copy local name
836 StringCchCopy( StringZone,
837 pNfsNetResource->LocalNameLength,
838 pNfsNetResource->LocalName );
839 pNetResource->lpLocalName = StringZone;
840 StringZone += pNfsNetResource->LocalNameLength/sizeof(WCHAR);
841 // copy remote name
842 StringCchCopy( StringZone,
843 pNfsNetResource->RemoteNameLength,
844 pNfsNetResource->RemoteName );
845 pNetResource->lpRemoteName = StringZone;
846 StringZone += pNfsNetResource->RemoteNameLength/sizeof(WCHAR);
847 // copy comment
848 pNetResource->lpComment = StringZone;
849 *StringZone++ = L'A';
850 *StringZone++ = L'_';
851 *StringZone++ = L'O';
852 *StringZone++ = L'K';
853 *StringZone++ = L'\0';
854 // copy provider name
855 pNetResource->lpProvider = StringZone;
856 StringCbCopyW( StringZone, sizeof(NFS41_PROVIDER_NAME_U), NFS41_PROVIDER_NAME_U );
857 StringZone += sizeof(NFS41_PROVIDER_NAME_U)/sizeof(WCHAR);
858 EntriesCopied++;
859 // set new bottom of string zone
860 StringZone = (PWCHAR)( (PBYTE) StringZone - SpaceNeeded );
861 Status = WN_SUCCESS;
862 }
863 pNetResource++;
864 }
865 }
866 CloseSharedMemory( &hMutex, &hMemory, (PVOID*)&pSharedMemory);
867 }
868
869 *lpcCount = EntriesCopied;
870 *(PULONG) hEnum = Index;
871
872 DbgP((L"[aglo] NPEnumResource entries returned: %d\n", EntriesCopied));
873
874 return Status;
875 }
876
877 DWORD APIENTRY
878 NPCloseEnum(
879 HANDLE hEnum )
880 {
881 DbgP((L"[aglo] NPCloseEnum\n"));
882 HeapFree( GetProcessHeap( ), 0, (PVOID) hEnum );
883 return WN_SUCCESS;
884 }
885
886 DWORD APIENTRY
887 NPGetResourceParent(
888 LPNETRESOURCE lpNetResource,
889 LPVOID lpBuffer,
890 LPDWORD lpBufferSize )
891 {
892 DbgP(( L"[aglo] NPGetResourceParent: WN_NOT_SUPPORTED\n" ));
893 return WN_NOT_SUPPORTED;
894 }
895
896 DWORD APIENTRY
897 NPGetResourceInformation(
898 __in LPNETRESOURCE lpNetResource,
899 __out_bcount(*lpBufferSize) LPVOID lpBuffer,
900 __inout LPDWORD lpBufferSize,
901 __deref_out LPWSTR *lplpSystem )
902 {
903 DbgP(( L"[aglo] NPGetResourceInformation: WN_NOT_SUPPORTED\n" ));
904 return WN_NOT_SUPPORTED;
905 }
906
907 DWORD APIENTRY
908 NPGetUniversalName(
909 LPCWSTR lpLocalPath,
910 DWORD dwInfoLevel,
911 LPVOID lpBuffer,
912 LPDWORD lpBufferSize )
913 {
914 DbgP(( L"[aglo] NPGetUniversalName: WN_NOT_SUPPORTED\n" ));
915 return WN_NOT_SUPPORTED;
916 }