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 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 61 int filter(unsigned int code) 62 { 63 DbgP((L"####Got exception %u\n", code)); 64 return EXCEPTION_CONTINUE_SEARCH; 65 } 66 67 DWORD 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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