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