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 #ifndef __REACTOS__ 653 DbgP((TEXT("NPCancelConnection: Name Length %d Entry Name Length %d\n"), 654 pNetResource->LocalNameLength,pNetResource->LocalName)); 655 #else 656 DbgP((TEXT("NPCancelConnection: Name Length %d Entry Name Length %d\n"), 657 (wcslen(lpName) + 1) * sizeof(WCHAR), pNetResource->LocalNameLength)); 658 #endif 659 660 } 661 } 662 663 CloseSharedMemory( &hMutex, 664 &hMemory, 665 (PVOID)&pSharedMemory); 666 } 667 668 return Status; 669 } 670 671 DWORD APIENTRY 672 NPGetConnection( 673 __in LPWSTR lpLocalName, 674 __out_bcount(*lpBufferSize) LPWSTR lpRemoteName, 675 __inout LPDWORD lpBufferSize ) 676 { 677 DWORD Status = 0; 678 679 HANDLE hMutex, hMemory; 680 PNFS41NP_SHARED_MEMORY pSharedMemory; 681 682 Status = OpenSharedMemory( &hMutex, 683 &hMemory, 684 (PVOID)&pSharedMemory); 685 686 if (Status == WN_SUCCESS) 687 { 688 INT Index; 689 PNFS41NP_NETRESOURCE pNetResource; 690 Status = WN_NOT_CONNECTED; 691 692 for (Index = 0; Index < pSharedMemory->NextAvailableIndex; Index++) 693 { 694 pNetResource = &pSharedMemory->NetResources[Index]; 695 696 if (pNetResource->InUse) 697 { 698 if ( ( (wcslen(lpLocalName) + 1) * sizeof(WCHAR) == 699 pNetResource->LocalNameLength) 700 && ( !wcscmp(lpLocalName, pNetResource->LocalName) )) 701 { 702 if (*lpBufferSize < pNetResource->RemoteNameLength) 703 { 704 *lpBufferSize = pNetResource->RemoteNameLength; 705 Status = WN_MORE_DATA; 706 } 707 else 708 { 709 *lpBufferSize = pNetResource->RemoteNameLength; 710 CopyMemory( lpRemoteName, 711 pNetResource->RemoteName, 712 pNetResource->RemoteNameLength); 713 Status = WN_SUCCESS; 714 } 715 break; 716 } 717 } 718 } 719 720 CloseSharedMemory( &hMutex, &hMemory, (PVOID)&pSharedMemory); 721 } 722 723 return Status; 724 } 725 726 DWORD APIENTRY 727 NPOpenEnum( 728 DWORD dwScope, 729 DWORD dwType, 730 DWORD dwUsage, 731 LPNETRESOURCE lpNetResource, 732 LPHANDLE lphEnum ) 733 { 734 DWORD Status; 735 736 DbgP((L"[aglo] NPOpenEnum\n")); 737 738 *lphEnum = NULL; 739 740 switch ( dwScope ) 741 { 742 case RESOURCE_CONNECTED: 743 { 744 *lphEnum = HeapAlloc( GetProcessHeap( ), HEAP_ZERO_MEMORY, sizeof( ULONG ) ); 745 746 if (*lphEnum ) 747 { 748 Status = WN_SUCCESS; 749 } 750 else 751 { 752 Status = WN_OUT_OF_MEMORY; 753 } 754 break; 755 } 756 break; 757 758 case RESOURCE_CONTEXT: 759 default: 760 Status = WN_NOT_SUPPORTED; 761 break; 762 } 763 764 765 DbgP((L"[aglo] NPOpenEnum returning Status %lx\n",Status)); 766 767 return(Status); 768 } 769 770 DWORD APIENTRY 771 NPEnumResource( 772 HANDLE hEnum, 773 LPDWORD lpcCount, 774 LPVOID lpBuffer, 775 LPDWORD lpBufferSize) 776 { 777 DWORD Status = WN_SUCCESS; 778 ULONG EntriesCopied; 779 LPNETRESOURCE pNetResource; 780 ULONG SpaceNeeded = 0; 781 ULONG SpaceAvailable; 782 PWCHAR StringZone; 783 HANDLE hMutex, hMemory; 784 PNFS41NP_SHARED_MEMORY pSharedMemory; 785 PNFS41NP_NETRESOURCE pNfsNetResource; 786 INT Index = *(PULONG)hEnum; 787 788 789 DbgP((L"[aglo] NPEnumResource\n")); 790 791 DbgP((L"[aglo] NPEnumResource Count Requested %d\n", *lpcCount)); 792 793 pNetResource = (LPNETRESOURCE) lpBuffer; 794 SpaceAvailable = *lpBufferSize; 795 EntriesCopied = 0; 796 StringZone = (PWCHAR) ((PBYTE)lpBuffer + *lpBufferSize); 797 798 Status = OpenSharedMemory( &hMutex, 799 &hMemory, 800 (PVOID)&pSharedMemory); 801 802 if ( Status == WN_SUCCESS) 803 { 804 Status = WN_NO_MORE_ENTRIES; 805 for (Index = *(PULONG)hEnum; EntriesCopied < *lpcCount && 806 Index < pSharedMemory->NextAvailableIndex; Index++) 807 { 808 pNfsNetResource = &pSharedMemory->NetResources[Index]; 809 810 if (pNfsNetResource->InUse) 811 { 812 SpaceNeeded = sizeof( NETRESOURCE ); 813 SpaceNeeded += pNfsNetResource->LocalNameLength; 814 SpaceNeeded += pNfsNetResource->RemoteNameLength; 815 SpaceNeeded += 5 * sizeof(WCHAR); // comment 816 SpaceNeeded += sizeof(NFS41_PROVIDER_NAME_U); // provider name 817 if ( SpaceNeeded > SpaceAvailable ) 818 { 819 Status = WN_MORE_DATA; 820 DbgP((L"[aglo] NPEnumResource More Data Needed - %d\n", SpaceNeeded)); 821 *lpBufferSize = SpaceNeeded; 822 break; 823 } 824 else 825 { 826 SpaceAvailable -= SpaceNeeded; 827 828 pNetResource->dwScope = pNfsNetResource->dwScope; 829 pNetResource->dwType = pNfsNetResource->dwType; 830 pNetResource->dwDisplayType = pNfsNetResource->dwDisplayType; 831 pNetResource->dwUsage = pNfsNetResource->dwUsage; 832 833 // setup string area at opposite end of buffer 834 SpaceNeeded -= sizeof( NETRESOURCE ); 835 StringZone = (PWCHAR)( (PBYTE) StringZone - SpaceNeeded ); 836 // copy local name 837 StringCchCopy( StringZone, 838 pNfsNetResource->LocalNameLength, 839 pNfsNetResource->LocalName ); 840 pNetResource->lpLocalName = StringZone; 841 StringZone += pNfsNetResource->LocalNameLength/sizeof(WCHAR); 842 // copy remote name 843 StringCchCopy( StringZone, 844 pNfsNetResource->RemoteNameLength, 845 pNfsNetResource->RemoteName ); 846 pNetResource->lpRemoteName = StringZone; 847 StringZone += pNfsNetResource->RemoteNameLength/sizeof(WCHAR); 848 // copy comment 849 pNetResource->lpComment = StringZone; 850 *StringZone++ = L'A'; 851 *StringZone++ = L'_'; 852 *StringZone++ = L'O'; 853 *StringZone++ = L'K'; 854 *StringZone++ = L'\0'; 855 // copy provider name 856 pNetResource->lpProvider = StringZone; 857 StringCbCopyW( StringZone, sizeof(NFS41_PROVIDER_NAME_U), NFS41_PROVIDER_NAME_U ); 858 StringZone += sizeof(NFS41_PROVIDER_NAME_U)/sizeof(WCHAR); 859 EntriesCopied++; 860 // set new bottom of string zone 861 StringZone = (PWCHAR)( (PBYTE) StringZone - SpaceNeeded ); 862 Status = WN_SUCCESS; 863 } 864 pNetResource++; 865 } 866 } 867 CloseSharedMemory( &hMutex, &hMemory, (PVOID*)&pSharedMemory); 868 } 869 870 *lpcCount = EntriesCopied; 871 *(PULONG) hEnum = Index; 872 873 DbgP((L"[aglo] NPEnumResource entries returned: %d\n", EntriesCopied)); 874 875 return Status; 876 } 877 878 DWORD APIENTRY 879 NPCloseEnum( 880 HANDLE hEnum ) 881 { 882 DbgP((L"[aglo] NPCloseEnum\n")); 883 HeapFree( GetProcessHeap( ), 0, (PVOID) hEnum ); 884 return WN_SUCCESS; 885 } 886 887 DWORD APIENTRY 888 NPGetResourceParent( 889 LPNETRESOURCE lpNetResource, 890 LPVOID lpBuffer, 891 LPDWORD lpBufferSize ) 892 { 893 DbgP(( L"[aglo] NPGetResourceParent: WN_NOT_SUPPORTED\n" )); 894 return WN_NOT_SUPPORTED; 895 } 896 897 DWORD APIENTRY 898 NPGetResourceInformation( 899 __in LPNETRESOURCE lpNetResource, 900 __out_bcount(*lpBufferSize) LPVOID lpBuffer, 901 __inout LPDWORD lpBufferSize, 902 __deref_out LPWSTR *lplpSystem ) 903 { 904 DbgP(( L"[aglo] NPGetResourceInformation: WN_NOT_SUPPORTED\n" )); 905 return WN_NOT_SUPPORTED; 906 } 907 908 DWORD APIENTRY 909 NPGetUniversalName( 910 LPCWSTR lpLocalPath, 911 DWORD dwInfoLevel, 912 LPVOID lpBuffer, 913 LPDWORD lpBufferSize ) 914 { 915 DbgP(( L"[aglo] NPGetUniversalName: WN_NOT_SUPPORTED\n" )); 916 return WN_NOT_SUPPORTED; 917 } 918