Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1727 lines
47 KiB

  1. /*++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. smbmrxnp.c
  5. Abstract:
  6. This module implements the routines required for interaction with network
  7. provider router interface in NT
  8. Notes:
  9. This module has been builkt and tested only in UNICODE environment
  10. --*/
  11. #include <windows.h>
  12. #include <windef.h>
  13. #include <winbase.h>
  14. #include <winsvc.h>
  15. #include <winnetwk.h>
  16. #include <npapi.h>
  17. #include <lmwksta.h>
  18. #include <devioctl.h>
  19. // include files from the smb inc directory
  20. #include <smbmrx.h>
  21. #ifndef UNICODE_STRING
  22. typedef struct _UNICODE_STRING {
  23. USHORT Length;
  24. USHORT MaximumLength;
  25. PWSTR Buffer;
  26. } UNICODE_STRING;
  27. typedef UNICODE_STRING *PUNICODE_STRING;
  28. #endif
  29. #ifndef FILE_FULL_EA_INFORMATION
  30. typedef struct _FILE_FULL_EA_INFORMATION {
  31. ULONG NextEntryOffset;
  32. UCHAR Flags;
  33. UCHAR EaNameLength;
  34. USHORT EaValueLength;
  35. CHAR EaName[1];
  36. } FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;
  37. #endif
  38. #define MAX_EA_NAME_LEN sizeof("UserName\0")
  39. #define MAX_CONNECT_INFO_SIZE \
  40. 3 * sizeof(FILE_FULL_EA_INFORMATION) + \
  41. sizeof(SMBMRX_CONNECTINFO) + \
  42. 4 * MAX_PATH + \
  43. 3 * MAX_EA_NAME_LEN
  44. typedef struct _SMBMRXNP_ENUMERATION_HANDLE_ {
  45. INT LastIndex;
  46. } SMBMRXNP_ENUMERATION_HANDLE,
  47. *PSMBMRXNP_ENUMERATION_HANDLE;
  48. #ifdef DBG
  49. #define DbgP(_x_) DbgPrint _x_
  50. #else
  51. #define DbgP(_x_)
  52. #endif
  53. ULONG _cdecl DbgPrint( LPTSTR Format, ... );
  54. #define TRACE_TAG L"SMBMRXNP: "
  55. // The debug level for this module
  56. // the SMB mini redirector and provider name. The original constants
  57. // are defined in smbmrx.h
  58. UNICODE_STRING SmbMRxDeviceName = {
  59. sizeof(DD_SMBMRX_FS_DEVICE_NAME_U),
  60. sizeof(DD_SMBMRX_FS_DEVICE_NAME_U),
  61. DD_SMBMRX_FS_DEVICE_NAME_U
  62. };
  63. UNICODE_STRING SmbMrxProviderName = {
  64. sizeof(SMBMRX_PROVIDER_NAME_U),
  65. sizeof(SMBMRX_PROVIDER_NAME_U),
  66. SMBMRX_PROVIDER_NAME_U
  67. };
  68. DWORD
  69. OpenSharedMemory(
  70. PHANDLE phMutex,
  71. PHANDLE phMemory,
  72. PVOID *pMemory
  73. )
  74. /*++
  75. Routine Description:
  76. This routine opens the shared memory for exclusive manipulation
  77. Arguments:
  78. phMutex - the mutex handle
  79. phMemory - the memory handle
  80. pMemory - a ptr. to the shared memory which is set if successful
  81. Return Value:
  82. WN_SUCCESS -- if successful
  83. --*/
  84. {
  85. DWORD dwStatus;
  86. DbgP((TEXT("OpenSharedMemory\n")));
  87. *phMutex = 0;
  88. *phMemory = 0;
  89. *pMemory = NULL;
  90. *phMutex = OpenMutex(SYNCHRONIZE,
  91. FALSE,
  92. SMBMRXNP_MUTEX_NAME);
  93. if (*phMutex == NULL)
  94. {
  95. dwStatus = GetLastError();
  96. DbgP((TEXT("OpenSharedMemory: OpenMutex failed\n")));
  97. goto OpenSharedMemoryAbort1;
  98. }
  99. DbgP((TEXT("OpenSharedMemory: Calling WaitForSingleObject\n")));
  100. WaitForSingleObject(*phMutex, INFINITE);
  101. *phMemory = OpenFileMapping(FILE_MAP_WRITE,
  102. FALSE,
  103. SMBMRXNP_SHARED_MEMORY_NAME);
  104. if (*phMemory == NULL)
  105. {
  106. dwStatus = GetLastError();
  107. DbgP((TEXT("OpenSharedMemory: OpenFileMapping failed\n")));
  108. goto OpenSharedMemoryAbort2;
  109. }
  110. *pMemory = MapViewOfFile(*phMemory, FILE_MAP_WRITE, 0, 0, 0);
  111. if (*pMemory == NULL)
  112. {
  113. dwStatus = GetLastError();
  114. DbgP((TEXT("OpenSharedMemory: MapViewOfFile failed\n")));
  115. goto OpenSharedMemoryAbort3;
  116. }
  117. DbgP((TEXT("OpenSharedMemory: return ERROR_SUCCESS\n")));
  118. return ERROR_SUCCESS;
  119. OpenSharedMemoryAbort3:
  120. CloseHandle(*phMemory);
  121. OpenSharedMemoryAbort2:
  122. ReleaseMutex(*phMutex);
  123. CloseHandle(*phMutex);
  124. *phMutex = NULL;
  125. OpenSharedMemoryAbort1:
  126. DbgP((TEXT("OpenSharedMemory: return dwStatus: %d\n"), dwStatus));
  127. return dwStatus;
  128. }
  129. VOID
  130. CloseSharedMemory(
  131. PHANDLE hMutex,
  132. PHANDLE hMemory,
  133. PVOID *pMemory )
  134. /*++
  135. Routine Description:
  136. This routine relinquishes control of the shared memory after exclusive
  137. manipulation
  138. Arguments:
  139. hMutex - the mutex handle
  140. hMemory - the memory handle
  141. pMemory - a ptr. to the shared memory which is set if successful
  142. Return Value:
  143. --*/
  144. {
  145. DbgP((TEXT("CloseSharedMemory\n")));
  146. if (*pMemory)
  147. {
  148. UnmapViewOfFile(*pMemory);
  149. *pMemory = NULL;
  150. }
  151. if (*hMemory)
  152. {
  153. CloseHandle(*hMemory);
  154. *hMemory = 0;
  155. }
  156. if (*hMutex)
  157. {
  158. if (ReleaseMutex(*hMutex) == FALSE)
  159. {
  160. DbgP((TEXT("CloseSharedMemory: ReleaseMutex error: %d\n"), GetLastError()));
  161. }
  162. CloseHandle(*hMutex);
  163. *hMutex = 0;
  164. }
  165. DbgP((TEXT("CloseSharedMemory: Return\n")));
  166. }
  167. DWORD APIENTRY
  168. NPGetCaps(
  169. DWORD nIndex )
  170. /*++
  171. Routine Description:
  172. This routine returns the capabilities of the SMB Mini redirector
  173. network provider implementation
  174. Arguments:
  175. nIndex - category of capabilities desired
  176. Return Value:
  177. the appropriate capabilities
  178. --*/
  179. {
  180. switch (nIndex)
  181. {
  182. case WNNC_SPEC_VERSION:
  183. return WNNC_SPEC_VERSION51;
  184. case WNNC_NET_TYPE:
  185. return WNNC_NET_RDR2_SAMPLE;
  186. case WNNC_DRIVER_VERSION:
  187. #define WNNC_DRIVER(major,minor) (major*0x00010000 + minor)
  188. return WNNC_DRIVER(1, 0);
  189. case WNNC_CONNECTION:
  190. return WNNC_CON_GETCONNECTIONS | WNNC_CON_CANCELCONNECTION |
  191. WNNC_CON_ADDCONNECTION | WNNC_CON_ADDCONNECTION3;
  192. case WNNC_ENUMERATION:
  193. return WNNC_ENUM_LOCAL;
  194. case WNNC_START:
  195. case WNNC_USER:
  196. case WNNC_DIALOG:
  197. case WNNC_ADMIN:
  198. default:
  199. return 0;
  200. }
  201. }
  202. DWORD APIENTRY
  203. NPLogonNotify(
  204. PLUID lpLogonId,
  205. LPCWSTR lpAuthentInfoType,
  206. LPVOID lpAuthentInfo,
  207. LPCWSTR lpPreviousAuthentInfoType,
  208. LPVOID lpPreviousAuthentInfo,
  209. LPWSTR lpStationName,
  210. LPVOID StationHandle,
  211. LPWSTR *lpLogonScript)
  212. /*++
  213. Routine Description:
  214. This routine handles the logon notifications
  215. Arguments:
  216. lpLogonId -- the associated LUID
  217. lpAuthenInfoType - the authentication information type
  218. lpAuthenInfo - the authentication Information
  219. lpPreviousAuthentInfoType - the previous aunthentication information type
  220. lpPreviousAuthentInfo - the previous authentication information
  221. lpStationName - the logon station name
  222. LPVOID - logon station handle
  223. lpLogonScript - the logon script to be executed.
  224. Return Value:
  225. WN_SUCCESS
  226. Notes:
  227. This capability has not been implemented in the sample.
  228. --*/
  229. {
  230. *lpLogonScript = NULL;
  231. return WN_SUCCESS;
  232. }
  233. DWORD APIENTRY
  234. NPPasswordChangeNotify (
  235. LPCWSTR lpAuthentInfoType,
  236. LPVOID lpAuthentInfo,
  237. LPCWSTR lpPreviousAuthentInfoType,
  238. LPVOID lpPreviousAuthentInfo,
  239. LPWSTR lpStationName,
  240. LPVOID StationHandle,
  241. DWORD dwChangeInfo )
  242. /*++
  243. Routine Description:
  244. This routine handles the password change notifications
  245. Arguments:
  246. lpAuthenInfoType - the authentication information type
  247. lpAuthenInfo - the authentication Information
  248. lpPreviousAuthentInfoType - the previous aunthentication information type
  249. lpPreviousAuthentInfo - the previous authentication information
  250. lpStationName - the logon station name
  251. LPVOID - logon station handle
  252. dwChangeInfo - the password change information.
  253. Return Value:
  254. WN_NOT_SUPPORTED
  255. Notes:
  256. This capability has not been implemented in the sample.
  257. --*/
  258. {
  259. SetLastError(WN_NOT_SUPPORTED);
  260. return WN_NOT_SUPPORTED;
  261. }
  262. DWORD APIENTRY
  263. NPOpenEnum(
  264. DWORD dwScope,
  265. DWORD dwType,
  266. DWORD dwUsage,
  267. LPNETRESOURCE lpNetResource,
  268. LPHANDLE lphEnum )
  269. /*++
  270. Routine Description:
  271. This routine opens a handle for enumeration of resources. The only capability
  272. implemented in the sample is for enumerating connected shares
  273. Arguments:
  274. dwScope - the scope of enumeration
  275. dwType - the type of resources to be enumerated
  276. dwUsage - the usage parameter
  277. lpNetResource - a pointer to the desired NETRESOURCE struct.
  278. lphEnum - aptr. for passing nack the enumeration handle
  279. Return Value:
  280. WN_SUCCESS if successful, otherwise the appropriate error
  281. Notes:
  282. The sample only supports the notion of enumerating connected shares
  283. The handle passed back is merely the index of the last entry returned
  284. --*/
  285. {
  286. DWORD Status = 0;
  287. DbgP((TEXT("NPOpenEnum\n")));
  288. *lphEnum = NULL;
  289. switch (dwScope)
  290. {
  291. case RESOURCE_CONNECTED:
  292. {
  293. *lphEnum = LocalAlloc(
  294. LMEM_ZEROINIT,
  295. sizeof(SMBMRXNP_ENUMERATION_HANDLE));
  296. if (*lphEnum != NULL)
  297. {
  298. Status = WN_SUCCESS;
  299. }
  300. else
  301. {
  302. Status = WN_OUT_OF_MEMORY;
  303. }
  304. break;
  305. }
  306. break;
  307. case RESOURCE_CONTEXT:
  308. default:
  309. Status = WN_NOT_SUPPORTED;
  310. break;
  311. }
  312. DbgP((TEXT("NPOpenEnum returning Status %lx\n"),Status));
  313. return(Status);
  314. }
  315. DWORD APIENTRY
  316. NPEnumResource(
  317. HANDLE hEnum,
  318. LPDWORD lpcCount,
  319. LPVOID lpBuffer,
  320. LPDWORD lpBufferSize)
  321. /*++
  322. Routine Description:
  323. This routine uses the handle obtained by a call to NPOpenEnum for
  324. enuerating the connected shares
  325. Arguments:
  326. hEnum - the enumeration handle
  327. lpcCount - the number of resources returned
  328. lpBuffer - the buffere for passing back the entries
  329. lpBufferSize - the size of the buffer
  330. Return Value:
  331. WN_SUCCESS if successful, otherwise the appropriate error
  332. WN_NO_MORE_ENTRIES - if the enumeration has exhausted the entries
  333. WN_MORE_DATA - if nmore data is available
  334. Notes:
  335. The sample only supports the notion of enumerating connected shares
  336. The handle passed back is merely the index of the last entry returned
  337. --*/
  338. {
  339. DWORD Status = WN_SUCCESS;
  340. LPNETRESOURCEW pBufferResource;
  341. DWORD StringOffset;
  342. DWORD AvailableBufferSize;
  343. HANDLE hMutex, hMemory;
  344. PSMBMRXNP_ENUMERATION_HANDLE pEnumHandle;
  345. PSMBMRXNP_SHARED_MEMORY pSharedMemory;
  346. DbgP((TEXT("NPEnumResource\n")));
  347. DbgP((TEXT("NPEnumResource Count Requested %d\n"),*lpcCount));
  348. AvailableBufferSize = *lpBufferSize;
  349. StringOffset = *lpBufferSize;
  350. pBufferResource = (LPNETRESOURCEW)lpBuffer;
  351. pEnumHandle = (PSMBMRXNP_ENUMERATION_HANDLE)hEnum;
  352. *lpcCount = 0;
  353. if (pEnumHandle->LastIndex >= SMBMRXNP_MAX_DEVICES)
  354. {
  355. return WN_NO_MORE_ENTRIES;
  356. }
  357. Status = OpenSharedMemory(
  358. &hMutex,
  359. &hMemory,
  360. (PVOID)&pSharedMemory);
  361. if (Status == WN_SUCCESS)
  362. {
  363. INT Index;
  364. PSMBMRXNP_NETRESOURCE pNetResource;
  365. DbgP((TEXT("NPEnumResource: Highest Index %d Number Of resources %d\n"),
  366. pSharedMemory->HighestIndexInUse,pSharedMemory->NumberOfResourcesInUse));
  367. for (Index = pEnumHandle->LastIndex; Index <= pSharedMemory->HighestIndexInUse; Index++) {
  368. pNetResource = &pSharedMemory->NetResources[Index];
  369. DbgP((TEXT("NPEnumResource: Examining Index %d\n"),Index));
  370. if (pNetResource->InUse)
  371. {
  372. DWORD ResourceSize;
  373. ResourceSize = sizeof(NETRESOURCE) +
  374. pNetResource->LocalNameLength + sizeof(WCHAR) +
  375. pNetResource->RemoteNameLength + sizeof(WCHAR) +
  376. SmbMrxProviderName.Length + sizeof(WCHAR);
  377. if (AvailableBufferSize >= ResourceSize)
  378. {
  379. *lpcCount = *lpcCount + 1;
  380. AvailableBufferSize -= ResourceSize;
  381. pBufferResource->dwScope = RESOURCE_CONNECTED;
  382. pBufferResource->dwType = pNetResource->dwType;
  383. pBufferResource->dwDisplayType = pNetResource->dwDisplayType;
  384. pBufferResource->dwUsage = pNetResource->dwUsage;
  385. DbgP((TEXT("NPEnumResource: Copying local name Index %d\n"),Index));
  386. // set up the strings in the resource
  387. StringOffset -= (pNetResource->LocalNameLength + sizeof(WCHAR));
  388. pBufferResource->lpLocalName = (PWCHAR)((PBYTE)lpBuffer + StringOffset);
  389. CopyMemory(pBufferResource->lpLocalName,
  390. pNetResource->LocalName,
  391. pNetResource->LocalNameLength);
  392. pBufferResource->lpLocalName[
  393. pNetResource->LocalNameLength/sizeof(WCHAR)] = L'\0';
  394. DbgP((TEXT("NPEnumResource: Copying remote name Index %d\n"),Index));
  395. StringOffset -= (pNetResource->RemoteNameLength + sizeof(WCHAR));
  396. pBufferResource->lpRemoteName = (PWCHAR)((PBYTE)lpBuffer + StringOffset);
  397. CopyMemory(pBufferResource->lpRemoteName,
  398. pNetResource->RemoteName,
  399. pNetResource->RemoteNameLength);
  400. pBufferResource->lpRemoteName[
  401. pNetResource->RemoteNameLength/sizeof(WCHAR)] = L'\0';
  402. DbgP((TEXT("NPEnumResource: Copying provider name Index %d\n"),Index));
  403. StringOffset -= (SmbMrxProviderName.Length + sizeof(WCHAR));
  404. pBufferResource->lpProvider = (PWCHAR)((PBYTE)lpBuffer + StringOffset);
  405. CopyMemory(pBufferResource->lpProvider,
  406. SmbMrxProviderName.Buffer,
  407. SmbMrxProviderName.Length);
  408. pBufferResource->lpProvider[
  409. SmbMrxProviderName.Length/sizeof(WCHAR)] = L'\0';
  410. pBufferResource->lpComment = NULL;
  411. pBufferResource++;
  412. }
  413. else
  414. {
  415. DbgP((TEXT("NPEnumResource: Buffer Overflow Index %d\n"),Index));
  416. Status = WN_MORE_DATA;
  417. break;
  418. }
  419. }
  420. }
  421. pEnumHandle->LastIndex = Index;
  422. if ((Status == WN_SUCCESS) &&
  423. (pEnumHandle->LastIndex > pSharedMemory->HighestIndexInUse) &&
  424. (*lpcCount == 0))
  425. {
  426. Status = WN_NO_MORE_ENTRIES;
  427. }
  428. CloseSharedMemory(
  429. &hMutex,
  430. &hMemory,
  431. (PVOID)&pSharedMemory);
  432. }
  433. DbgP((TEXT("NPEnumResource returning Count %d\n"),*lpcCount));
  434. DbgP((TEXT("NPEnumResource returning Status %lx\n"),Status));
  435. return Status;
  436. }
  437. DWORD APIENTRY
  438. NPCloseEnum(
  439. HANDLE hEnum )
  440. /*++
  441. Routine Description:
  442. This routine closes the handle for enumeration of resources.
  443. Arguments:
  444. hEnum - the enumeration handle
  445. Return Value:
  446. WN_SUCCESS if successful, otherwise the appropriate error
  447. Notes:
  448. The sample only supports the notion of enumerating connected shares
  449. --*/
  450. {
  451. DbgP((TEXT("NPCloseEnum\n")));
  452. LocalFree(hEnum);
  453. return WN_SUCCESS;
  454. }
  455. ULONG
  456. SendToMiniRdr(
  457. IN ULONG IoctlCode,
  458. IN PVOID InputDataBuf,
  459. IN ULONG InputDataLen,
  460. IN PVOID OutputDataBuf,
  461. IN PULONG pOutputDataLen)
  462. /*++
  463. Routine Description:
  464. This routine sends a device ioctl to the Mini Rdr.
  465. Arguments:
  466. IoctlCode - Function code for the Mini Rdr driver
  467. InputDataBuf - Input buffer pointer
  468. InputDataLen - Lenth of the input buffer
  469. OutputDataBuf - Output buffer pointer
  470. pOutputDataLen - Pointer to the length of the output buffer
  471. Return Value:
  472. WN_SUCCESS if successful, otherwise the appropriate error
  473. Notes:
  474. --*/
  475. {
  476. HANDLE DeviceHandle; // The mini rdr device handle
  477. ULONG BytesRet;
  478. BOOL rc;
  479. ULONG Status;
  480. Status = WN_SUCCESS;
  481. // Grab a handle to the redirector device object
  482. DeviceHandle = CreateFile(
  483. DD_SMBMRX_USERMODE_DEV_NAME,
  484. GENERIC_READ | GENERIC_WRITE,
  485. FILE_SHARE_READ | FILE_SHARE_WRITE,
  486. (LPSECURITY_ATTRIBUTES)NULL,
  487. OPEN_EXISTING,
  488. 0,
  489. (HANDLE) NULL );
  490. if ( INVALID_HANDLE_VALUE != DeviceHandle )
  491. {
  492. rc = DeviceIoControl( DeviceHandle,
  493. IoctlCode,
  494. InputDataBuf,
  495. InputDataLen,
  496. OutputDataBuf,
  497. *pOutputDataLen,
  498. pOutputDataLen,
  499. NULL );
  500. if ( !rc )
  501. {
  502. DbgP(( L"SendToMiniRdr - returning error from DeviceIoctl\n" ));
  503. Status = GetLastError( );
  504. }
  505. else
  506. {
  507. DbgP(( L"SendToMiniRdr - The DeviceIoctl call succeded\n" ));
  508. }
  509. CloseHandle(DeviceHandle);
  510. }
  511. else
  512. {
  513. Status = GetLastError( );
  514. DbgP(( L"SendToMiniRdr - error %lx opening device \n", Status ));
  515. }
  516. return Status;
  517. }
  518. ULONG FillInEaBuffer( LPTSTR pUserName, LPTSTR pPassword, PBYTE pEaData )
  519. {
  520. PFILE_FULL_EA_INFORMATION thisEa = (PFILE_FULL_EA_INFORMATION) pEaData;
  521. PBYTE valuePtr = pEaData;
  522. PWKSTA_INFO_100 WkStaInfo;
  523. ULONG status;
  524. PWCHAR pDomain;
  525. // get the domain that this workstation is a member of
  526. status = NetWkstaGetInfo( NULL, 100, (PBYTE *) &WkStaInfo );
  527. if ( status == ERROR_SUCCESS )
  528. {
  529. pDomain = WkStaInfo->wki100_langroup;
  530. }
  531. else
  532. {
  533. pDomain = NULL;
  534. }
  535. DbgP((L"FillInEaBuffer - domain name=%s\n", pDomain));
  536. thisEa->EaValueLength = 0;
  537. thisEa->NextEntryOffset = 0;
  538. // Set the user name EA
  539. if ( pUserName )
  540. {
  541. thisEa->Flags = 0;
  542. thisEa->EaNameLength = sizeof("UserName");
  543. CopyMemory( thisEa->EaName, "UserName\0", thisEa->EaNameLength + 1 );
  544. valuePtr = (PBYTE) thisEa->EaName + thisEa->EaNameLength + 1;
  545. thisEa->EaValueLength = (USHORT)( *pUserName ? lstrlenW( pUserName ) : 1 ) * sizeof( WCHAR );
  546. CopyMemory( valuePtr, pUserName, thisEa->EaValueLength );
  547. thisEa->NextEntryOffset = (ULONG)(((PBYTE) valuePtr + thisEa->EaValueLength ) -
  548. (PBYTE) thisEa);
  549. thisEa->NextEntryOffset = ((thisEa->NextEntryOffset + 3) / sizeof(LONG)) * sizeof(LONG);
  550. }
  551. // Set the password EA.
  552. if ( pPassword )
  553. {
  554. thisEa = (PFILE_FULL_EA_INFORMATION) ((PBYTE) thisEa + thisEa->NextEntryOffset);
  555. thisEa->Flags = 0;
  556. thisEa->EaNameLength = sizeof("Password");
  557. CopyMemory( thisEa->EaName, "Password\0", thisEa->EaNameLength + 1 );
  558. valuePtr = (PBYTE) thisEa->EaName + thisEa->EaNameLength + 1;
  559. thisEa->EaValueLength = (USHORT)( *pPassword ? lstrlenW( pPassword ) : 1 ) * sizeof( WCHAR );
  560. CopyMemory( valuePtr, pPassword, thisEa->EaValueLength );
  561. thisEa->NextEntryOffset = (ULONG)(((PBYTE) valuePtr + thisEa->EaValueLength ) -
  562. (PBYTE) thisEa);
  563. thisEa->NextEntryOffset = ((thisEa->NextEntryOffset + 3) / sizeof(LONG)) * sizeof(LONG);
  564. }
  565. // Set the domain EA
  566. if ( pDomain )
  567. {
  568. thisEa = (PFILE_FULL_EA_INFORMATION) ((PBYTE) thisEa + thisEa->NextEntryOffset);
  569. thisEa->Flags = 0;
  570. thisEa->EaNameLength = sizeof("Domain");
  571. RtlCopyMemory( thisEa->EaName, "Domain\0", thisEa->EaNameLength + 1 );
  572. valuePtr = (PBYTE) thisEa->EaName + thisEa->EaNameLength + 1;
  573. thisEa->EaValueLength = (USHORT)( *pDomain ? lstrlenW( pDomain ) : 1 ) * sizeof( WCHAR );
  574. RtlCopyMemory( valuePtr, pDomain, thisEa->EaValueLength );
  575. thisEa->NextEntryOffset = 0;
  576. }
  577. thisEa->NextEntryOffset = 0;
  578. return (ULONG)(((PBYTE) valuePtr + thisEa->EaValueLength) - (PBYTE) pEaData);
  579. }
  580. DWORD APIENTRY
  581. NPAddConnection(
  582. LPNETRESOURCE lpNetResource,
  583. LPWSTR lpPassword,
  584. LPWSTR lpUserName )
  585. /*++
  586. Routine Description:
  587. This routine adds a connection to the list of connections associated
  588. with this network provider
  589. Arguments:
  590. lpNetResource - the NETRESOURCE struct
  591. lpPassword - the password
  592. lpUserName - the user name
  593. Return Value:
  594. WN_SUCCESS if successful, otherwise the appropriate error
  595. Notes:
  596. --*/
  597. {
  598. return NPAddConnection3(NULL, lpNetResource, lpPassword, lpUserName, 0);
  599. }
  600. DWORD APIENTRY
  601. NPAddConnection3(
  602. HWND hwndOwner,
  603. LPNETRESOURCE lpNetResource,
  604. LPWSTR lpPassword,
  605. LPWSTR lpUserName,
  606. DWORD dwFlags )
  607. /*++
  608. Routine Description:
  609. This routine adds a connection to the list of connections associated
  610. with this network provider
  611. Arguments:
  612. hwndOwner - the owner handle
  613. lpNetResource - the NETRESOURCE struct
  614. lpPassword - the password
  615. lpUserName - the user name
  616. dwFlags - flags for the connection
  617. Return Value:
  618. WN_SUCCESS if successful, otherwise the appropriate error
  619. Notes:
  620. The current sample does not handle explicitly passesd in credentials. Normally
  621. the credential information is passed in as EA parameters to the associated
  622. mini redirector for further manipulation
  623. --*/
  624. {
  625. DWORD Status = 0;
  626. UNICODE_STRING ConnectionName;
  627. PWCHAR pLocalName,pRemoteName;
  628. USHORT LocalNameLength,RemoteNameLength;
  629. HANDLE hConnection;
  630. ULONG TransferBytes;
  631. WCHAR NullStr[] = L"\0\0";
  632. PWCHAR pUserName;
  633. PWCHAR pPassword;
  634. PWKSTA_USER_INFO_0 WkStaUserInfo;
  635. PSMBMRX_CONNECTINFO ConnectInfo;
  636. DbgP((TEXT("NPAddConnection3: Incoming UserName - %s, Password - %s\n"),
  637. lpUserName, lpPassword ));
  638. // if no user specified, get the current logged on user
  639. if ( lpUserName == NULL )
  640. {
  641. Status = NetWkstaUserGetInfo( NULL, 0, (PBYTE *)&WkStaUserInfo );
  642. if ( Status == ERROR_SUCCESS )
  643. {
  644. pUserName = WkStaUserInfo->wkui0_username;
  645. }
  646. else
  647. {
  648. pUserName = NullStr;
  649. }
  650. }
  651. else
  652. {
  653. pUserName = lpUserName;
  654. }
  655. if ( lpPassword == NULL )
  656. {
  657. pPassword = NullStr; // use default password
  658. pPassword[1] = '\0'; // reset empty flag
  659. }
  660. else if ( *lpPassword == L'\0' )
  661. {
  662. pPassword = NullStr;
  663. pPassword[1] = '1'; // flag the password as "Empty"
  664. }
  665. else
  666. {
  667. pPassword = lpPassword;
  668. }
  669. Status = ERROR_SUCCESS;
  670. DbgP((TEXT("NPAddConnection3: Outgoing UserName - %s, Password - %s\n"),
  671. lpUserName, lpPassword ));
  672. // The SMB mini supports only DISK type resources. The other resources
  673. // are not supported.
  674. if ((lpNetResource->lpRemoteName == NULL) ||
  675. (lpNetResource->lpRemoteName[0] != L'\\') ||
  676. (lpNetResource->lpRemoteName[1] != L'\\') ||
  677. (lpNetResource->dwType != RESOURCETYPE_DISK))
  678. {
  679. return WN_BAD_NETNAME;
  680. }
  681. //
  682. // The remote name is in the UNC format \\Server\Share. This name
  683. // needs to be translated to an appropriate NT name in order to
  684. // issue the request to the underlying mini redirector to create the
  685. // connection.
  686. //
  687. // The NT style name is of the form
  688. //
  689. // \device\smbminiredirector\;<DriveLetter>:\Server\Share
  690. //
  691. // The additional ; is required by the new RDR for extensibility.
  692. //
  693. pLocalName = lpNetResource->lpLocalName;
  694. pRemoteName = lpNetResource->lpRemoteName;
  695. // skip past the first back slash since the name to be appended for the
  696. // NT name does not require this.
  697. pRemoteName++;
  698. if (pLocalName != NULL) {
  699. LocalNameLength = wcslen(pLocalName) * sizeof(WCHAR);
  700. } else {
  701. LocalNameLength = 0;
  702. }
  703. RemoteNameLength = (wcslen(pRemoteName) - 1) * sizeof(WCHAR);
  704. ConnectionName.MaximumLength = (USHORT)(SmbMRxDeviceName.Length +
  705. (USHORT)RemoteNameLength +
  706. ((pLocalName != NULL)
  707. ? (LocalNameLength + sizeof(WCHAR)) : 0) + // space for ;
  708. sizeof(WCHAR));
  709. ConnectionName.Length = ConnectionName.MaximumLength;
  710. ConnectionName.Buffer = LocalAlloc( LMEM_ZEROINIT,
  711. ConnectionName.Length + sizeof(WCHAR));
  712. if (ConnectionName.Buffer == NULL)
  713. {
  714. return GetLastError();
  715. }
  716. // Copy the name into the buffer
  717. CopyMemory( ConnectionName.Buffer,
  718. SmbMRxDeviceName.Buffer,
  719. SmbMRxDeviceName.Length);
  720. wcscat(ConnectionName.Buffer, L"\\");
  721. wcscat(ConnectionName.Buffer, L";");
  722. if (pLocalName != NULL)
  723. {
  724. wcscat(ConnectionName.Buffer, pLocalName);
  725. }
  726. wcscat(ConnectionName.Buffer, pRemoteName);
  727. ConnectInfo = (PSMBMRX_CONNECTINFO) LocalAlloc( LMEM_ZEROINIT, MAX_CONNECT_INFO_SIZE );
  728. if ( ConnectInfo )
  729. {
  730. ConnectInfo->ConnectionNameOffset = 0;
  731. ConnectInfo->ConnectionNameLength = ConnectionName.Length;
  732. CopyMemory( ConnectInfo->InfoArea, ConnectionName.Buffer, ConnectionName.Length );
  733. ConnectInfo->EaDataOffset = ConnectInfo->ConnectionNameOffset +
  734. ConnectInfo->ConnectionNameLength;
  735. // check for the "no password" flag
  736. if ( pPassword[0] == L'\0' && pPassword[1] == L'1' )
  737. {
  738. pPassword = NULL;
  739. }
  740. ConnectInfo->EaDataLength = FillInEaBuffer( pUserName,
  741. pPassword,
  742. (PBYTE) ConnectInfo->InfoArea +
  743. ConnectInfo->EaDataOffset );
  744. TransferBytes = 0;
  745. Status = SendToMiniRdr( IOCTL_SMBMRX_ADDCONN,
  746. ConnectInfo,
  747. MAX_CONNECT_INFO_SIZE,
  748. NULL,
  749. &TransferBytes );
  750. LocalFree( ConnectInfo );
  751. }
  752. else
  753. {
  754. Status = WN_OUT_OF_MEMORY;
  755. }
  756. if ((Status == WN_SUCCESS) && (pLocalName != NULL))
  757. {
  758. WCHAR TempBuf[64];
  759. if (!QueryDosDeviceW(
  760. pLocalName,
  761. TempBuf,
  762. 64))
  763. {
  764. if (GetLastError() != ERROR_FILE_NOT_FOUND)
  765. {
  766. //
  767. // Most likely failure occurred because our output
  768. // buffer is too small. It still means someone already
  769. // has an existing symbolic link for this device.
  770. //
  771. Status = ERROR_ALREADY_ASSIGNED;
  772. }
  773. else
  774. {
  775. //
  776. // ERROR_FILE_NOT_FOUND (translated from OBJECT_NAME_NOT_FOUND)
  777. // means it does not exist and we can redirect this device.
  778. //
  779. // Create a symbolic link object to the device we are redirecting
  780. //
  781. if (!DefineDosDeviceW(
  782. DDD_RAW_TARGET_PATH |
  783. DDD_NO_BROADCAST_SYSTEM,
  784. pLocalName,
  785. ConnectionName.Buffer))
  786. {
  787. Status = GetLastError();
  788. }
  789. else
  790. {
  791. Status = WN_SUCCESS;
  792. }
  793. }
  794. }
  795. else
  796. {
  797. //
  798. // QueryDosDevice successfully an existing symbolic link--
  799. // somebody is already using this device.
  800. //
  801. Status = ERROR_ALREADY_ASSIGNED;
  802. }
  803. }
  804. else
  805. {
  806. DbgP((TEXT("SendToMiniRdr returned %lx\n"),Status));
  807. }
  808. if (Status == WN_SUCCESS)
  809. {
  810. INT Index;
  811. HANDLE hMutex, hMemory;
  812. BOOLEAN FreeEntryFound = FALSE;
  813. PSMBMRXNP_SHARED_MEMORY pSharedMemory;
  814. // The connection was established and the local device mapping
  815. // added. Include this in the list of mapped devices.
  816. Status = OpenSharedMemory(
  817. &hMutex,
  818. &hMemory,
  819. (PVOID)&pSharedMemory);
  820. if (Status == WN_SUCCESS)
  821. {
  822. DbgP((TEXT("NPAddConnection3: Highest Index %d Number Of resources %d\n"),
  823. pSharedMemory->HighestIndexInUse,pSharedMemory->NumberOfResourcesInUse));
  824. Index = 0;
  825. while (Index < pSharedMemory->HighestIndexInUse)
  826. {
  827. if (!pSharedMemory->NetResources[Index].InUse)
  828. {
  829. FreeEntryFound = TRUE;
  830. break;
  831. }
  832. Index++;
  833. }
  834. if (!FreeEntryFound &&
  835. (pSharedMemory->HighestIndexInUse < SMBMRXNP_MAX_DEVICES))
  836. {
  837. pSharedMemory->HighestIndexInUse += 1;
  838. Index = pSharedMemory->HighestIndexInUse;
  839. FreeEntryFound = TRUE;
  840. }
  841. if (FreeEntryFound)
  842. {
  843. PSMBMRXNP_NETRESOURCE pSmbMrxNetResource;
  844. pSharedMemory->NumberOfResourcesInUse += 1;
  845. pSmbMrxNetResource = &pSharedMemory->NetResources[Index];
  846. pSmbMrxNetResource->InUse = TRUE;
  847. pSmbMrxNetResource->dwScope = lpNetResource->dwScope;
  848. pSmbMrxNetResource->dwType = lpNetResource->dwType;
  849. pSmbMrxNetResource->dwDisplayType = lpNetResource->dwDisplayType;
  850. pSmbMrxNetResource->dwUsage = RESOURCEUSAGE_CONNECTABLE;
  851. pSmbMrxNetResource->LocalNameLength = LocalNameLength;
  852. pSmbMrxNetResource->RemoteNameLength = wcslen(lpNetResource->lpRemoteName) * sizeof(WCHAR);
  853. pSmbMrxNetResource->ConnectionNameLength = ConnectionName.Length;
  854. // Copy the local name
  855. CopyMemory( pSmbMrxNetResource->LocalName,
  856. lpNetResource->lpLocalName,
  857. pSmbMrxNetResource->LocalNameLength);
  858. // Copy the remote name
  859. CopyMemory( pSmbMrxNetResource->RemoteName,
  860. lpNetResource->lpRemoteName,
  861. pSmbMrxNetResource->RemoteNameLength);
  862. // Copy the connection name
  863. CopyMemory( pSmbMrxNetResource->ConnectionName,
  864. ConnectionName.Buffer,
  865. pSmbMrxNetResource->ConnectionNameLength);
  866. //
  867. // Copy the Auth info
  868. //
  869. // WARNING : security hole using shared memory..Developers must use alternate methods to maintain use table.
  870. //
  871. lstrcpyn( pSmbMrxNetResource->UserName, pUserName, MAX_PATH);
  872. if ( *pPassword )
  873. {
  874. lstrcpyn( pSmbMrxNetResource->Password, pPassword, MAX_PATH);
  875. }
  876. else
  877. {
  878. CopyMemory( pSmbMrxNetResource->Password, pPassword, 3 * sizeof(WCHAR) );
  879. }
  880. }
  881. else
  882. {
  883. Status = WN_NO_MORE_DEVICES;
  884. }
  885. CloseSharedMemory( &hMutex,
  886. &hMemory,
  887. (PVOID)&pSharedMemory);
  888. }
  889. else
  890. {
  891. DbgP((TEXT("NpAddConnection3: OpenSharedMemory returned %lx\n"),Status));
  892. }
  893. }
  894. return Status;
  895. }
  896. DWORD APIENTRY
  897. NPCancelConnection(
  898. LPWSTR lpName,
  899. BOOL fForce )
  900. /*++
  901. Routine Description:
  902. This routine cancels ( deletes ) a connection from the list of connections
  903. associated with this network provider
  904. Arguments:
  905. lpName - name of the connection
  906. fForce - forcefully delete the connection
  907. Return Value:
  908. WN_SUCCESS if successful, otherwise the appropriate error
  909. Notes:
  910. --*/
  911. {
  912. BOOL bLocalName = TRUE;
  913. DWORD Status = 0;
  914. UNICODE_STRING Name;
  915. HANDLE hMutex, hMemory;
  916. PSMBMRXNP_SHARED_MEMORY pSharedMemory;
  917. if (*lpName == L'\\' && *(lpName + 1) == L'\\')
  918. {
  919. bLocalName = FALSE;
  920. }
  921. DbgP((TEXT("NPCancelConnection\n")));
  922. DbgP((TEXT("NPCancelConnection: ConnectionName: %S\n"), lpName));
  923. Name.MaximumLength = Name.Length = wcslen(lpName) * sizeof(WCHAR);
  924. Name.Buffer = lpName;
  925. Status = OpenSharedMemory( &hMutex,
  926. &hMemory,
  927. (PVOID)&pSharedMemory);
  928. if (Status == WN_SUCCESS)
  929. {
  930. INT Index;
  931. BOOL EntryFound = FALSE;
  932. PSMBMRXNP_NETRESOURCE pNetResource;
  933. DbgP((TEXT("NPCancelConnection: Highest Index %d Number Of resources %d\n"),
  934. pSharedMemory->HighestIndexInUse,pSharedMemory->NumberOfResourcesInUse));
  935. for (Index = 0; Index <= pSharedMemory->HighestIndexInUse; Index++)
  936. {
  937. pNetResource = &pSharedMemory->NetResources[Index];
  938. if (pNetResource->InUse)
  939. {
  940. UNICODE_STRING EntryName;
  941. if (bLocalName)
  942. {
  943. EntryName.MaximumLength = pNetResource->LocalNameLength;
  944. EntryName.Length = EntryName.MaximumLength;
  945. EntryName.Buffer = pNetResource->LocalName;
  946. }
  947. else
  948. {
  949. EntryName.MaximumLength = pNetResource->RemoteNameLength;
  950. EntryName.Length = EntryName.MaximumLength;
  951. EntryName.Buffer = pNetResource->RemoteName;
  952. }
  953. DbgP((TEXT("NPCancelConnection: Name %S EntryName %S\n"),
  954. lpName,EntryName.Buffer));
  955. DbgP((TEXT("NPCancelConnection: Name Length %d Entry Name Length %d\n"),
  956. Name.Length,EntryName.Length));
  957. if (Name.Length == EntryName.Length)
  958. {
  959. if ( _wcsnicmp(Name.Buffer, EntryName.Buffer, Name.Length) == 0 )
  960. {
  961. EntryFound = TRUE;
  962. break;
  963. }
  964. }
  965. }
  966. }
  967. if (EntryFound)
  968. {
  969. PWCHAR pUserName;
  970. PWCHAR pPassword;
  971. PSMBMRX_CONNECTINFO ConnectInfo;
  972. UNICODE_STRING ConnectionName;
  973. ULONG TransferBytes;
  974. DbgP((TEXT("NPCancelConnection: Connection Found:\n")));
  975. ConnectionName.Length = pNetResource->ConnectionNameLength;
  976. ConnectionName.MaximumLength = ConnectionName.Length;
  977. ConnectionName.Buffer = pNetResource->ConnectionName;
  978. pUserName = pNetResource->UserName;
  979. pPassword = pNetResource->Password;
  980. ConnectInfo = (PSMBMRX_CONNECTINFO) LocalAlloc( LMEM_ZEROINIT, MAX_CONNECT_INFO_SIZE );
  981. if ( ConnectInfo )
  982. {
  983. ConnectInfo->ConnectionNameOffset = 0;
  984. ConnectInfo->ConnectionNameLength = ConnectionName.Length;
  985. CopyMemory( ConnectInfo->InfoArea, ConnectionName.Buffer, ConnectionName.Length );
  986. ConnectInfo->EaDataOffset = ConnectInfo->ConnectionNameOffset +
  987. ConnectInfo->ConnectionNameLength;
  988. // check for the "no password" flag
  989. if ( pPassword[0] == L'\0' && pPassword[1] == L'1' )
  990. {
  991. pPassword = NULL;
  992. }
  993. ConnectInfo->EaDataLength = FillInEaBuffer( pUserName,
  994. pPassword,
  995. (PBYTE) ConnectInfo->InfoArea +
  996. ConnectInfo->EaDataOffset );
  997. TransferBytes = 0;
  998. Status = SendToMiniRdr( IOCTL_SMBMRX_DELCONN,
  999. ConnectInfo,
  1000. MAX_CONNECT_INFO_SIZE,
  1001. NULL,
  1002. &TransferBytes );
  1003. LocalFree( ConnectInfo );
  1004. }
  1005. else
  1006. {
  1007. Status = WN_OUT_OF_MEMORY;
  1008. }
  1009. DbgP((TEXT("NPCancelConnection: SendToMiniRdr returned Status %lx\n"),Status));
  1010. if ( bLocalName )
  1011. {
  1012. if (DefineDosDevice(DDD_REMOVE_DEFINITION | DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE,
  1013. lpName,
  1014. pNetResource->ConnectionName) == FALSE)
  1015. {
  1016. DbgP((TEXT("RemoveDosDevice: DefineDosDevice error: %d\n"), GetLastError()));
  1017. Status = GetLastError();
  1018. }
  1019. else
  1020. {
  1021. pNetResource->InUse = FALSE;
  1022. if (Index == pSharedMemory->HighestIndexInUse)
  1023. {
  1024. pSharedMemory->HighestIndexInUse -= 1;
  1025. pSharedMemory->NumberOfResourcesInUse -= 1;
  1026. }
  1027. }
  1028. }
  1029. }
  1030. CloseSharedMemory( &hMutex,
  1031. &hMemory,
  1032. (PVOID)&pSharedMemory);
  1033. }
  1034. return Status;
  1035. }
  1036. DWORD APIENTRY
  1037. NPGetConnection(
  1038. LPWSTR lpLocalName,
  1039. LPWSTR lpRemoteName,
  1040. LPDWORD lpBufferSize )
  1041. /*++
  1042. Routine Description:
  1043. This routine returns the information associated with a connection
  1044. Arguments:
  1045. lpLocalName - local name associated with the connection
  1046. lpRemoteName - the remote name associated with the connection
  1047. lpBufferSize - the remote name buffer size
  1048. Return Value:
  1049. WN_SUCCESS if successful, otherwise the appropriate error
  1050. Notes:
  1051. --*/
  1052. {
  1053. DWORD Status = 0;
  1054. UNICODE_STRING Name;
  1055. HANDLE hMutex, hMemory;
  1056. PSMBMRXNP_SHARED_MEMORY pSharedMemory;
  1057. Name.MaximumLength = Name.Length = wcslen(lpLocalName) * sizeof(WCHAR);
  1058. Name.Buffer = lpLocalName;
  1059. Status = OpenSharedMemory( &hMutex,
  1060. &hMemory,
  1061. (PVOID)&pSharedMemory);
  1062. if (Status == WN_SUCCESS)
  1063. {
  1064. INT Index;
  1065. BOOL EntryFound = FALSE;
  1066. PSMBMRXNP_NETRESOURCE pNetResource;
  1067. for (Index = 0; Index <= pSharedMemory->HighestIndexInUse; Index++)
  1068. {
  1069. pNetResource = &pSharedMemory->NetResources[Index];
  1070. if (pNetResource->InUse)
  1071. {
  1072. UNICODE_STRING EntryName;
  1073. EntryName.MaximumLength = pNetResource->LocalNameLength;
  1074. EntryName.Length = EntryName.MaximumLength;
  1075. EntryName.Buffer = pNetResource->LocalName;
  1076. if (Name.Length == EntryName.Length)
  1077. {
  1078. if ( wcsncmp( Name.Buffer, EntryName.Buffer, Name.Length/sizeof(WCHAR)) == 0 )
  1079. {
  1080. EntryFound = TRUE;
  1081. break;
  1082. }
  1083. }
  1084. }
  1085. }
  1086. if (EntryFound)
  1087. {
  1088. if (*lpBufferSize < pNetResource->RemoteNameLength)
  1089. {
  1090. *lpBufferSize = pNetResource->RemoteNameLength;
  1091. Status = ERROR_BUFFER_OVERFLOW;
  1092. }
  1093. else
  1094. {
  1095. *lpBufferSize = pNetResource->RemoteNameLength;
  1096. CopyMemory( lpRemoteName,
  1097. pNetResource->RemoteName,
  1098. pNetResource->RemoteNameLength);
  1099. Status = WN_SUCCESS;
  1100. }
  1101. }
  1102. else
  1103. {
  1104. Status = ERROR_NO_NET_OR_BAD_PATH;
  1105. }
  1106. CloseSharedMemory( &hMutex, &hMemory, (PVOID)&pSharedMemory);
  1107. }
  1108. return Status;
  1109. }
  1110. DWORD APIENTRY
  1111. NPGetResourceParent(
  1112. LPNETRESOURCE lpNetResource,
  1113. LPVOID lpBuffer,
  1114. LPDWORD lpBufferSize )
  1115. /*++
  1116. Routine Description:
  1117. This routine returns the parent of a given resource
  1118. Arguments:
  1119. lpNetResource - the NETRESOURCE struct
  1120. lpBuffer - the buffer for passing back the parent information
  1121. lpBufferSize - the buffer size
  1122. Return Value:
  1123. WN_NOT_SUPPORTED
  1124. Notes:
  1125. The current sample does not handle this call.
  1126. --*/
  1127. {
  1128. return WN_NOT_SUPPORTED;
  1129. }
  1130. DWORD APIENTRY
  1131. NPGetResourceInformation(
  1132. LPNETRESOURCE lpNetResource,
  1133. LPVOID lpBuffer,
  1134. LPDWORD lpBufferSize,
  1135. LPWSTR *lplpSystem )
  1136. /*++
  1137. Routine Description:
  1138. This routine returns the information associated net resource
  1139. Arguments:
  1140. lpNetResource - the NETRESOURCE struct
  1141. lpBuffer - the buffer for passing back the parent information
  1142. lpBufferSize - the buffer size
  1143. lplpSystem -
  1144. Return Value:
  1145. Notes:
  1146. --*/
  1147. {
  1148. DWORD dwStatus = 0;
  1149. LPNETRESOURCE pOutNetResource;
  1150. DbgP((TEXT("NPGetResourceInformation\n")));
  1151. return dwStatus;
  1152. }
  1153. DWORD APIENTRY
  1154. NPGetUniversalName(
  1155. LPCWSTR lpLocalPath,
  1156. DWORD dwInfoLevel,
  1157. LPVOID lpBuffer,
  1158. LPDWORD lpBufferSize )
  1159. /*++
  1160. Routine Description:
  1161. This routine returns the information associated net resource
  1162. Arguments:
  1163. lpLocalPath - the local path name
  1164. dwInfoLevel - the desired info level
  1165. lpBuffer - the buffer for the univeral name
  1166. lpBufferSize - the buffer size
  1167. Return Value:
  1168. WN_SUCCESS if successful
  1169. Notes:
  1170. --*/
  1171. {
  1172. DWORD dwStatus;
  1173. DWORD BufferRequired = 0;
  1174. DWORD UniversalNameLength = 0;
  1175. DWORD RemoteNameLength = 0;
  1176. DWORD RemainingPathLength = 0;
  1177. LPWSTR pDriveLetter,
  1178. pRemainingPath,
  1179. SourceStrings[3];
  1180. WCHAR RemoteName[MAX_PATH],
  1181. LocalPath[MAX_PATH],
  1182. UniversalName[MAX_PATH],
  1183. ReplacedChar;
  1184. DbgP((TEXT("NPGetUniversalName: lpLocalPath: %S InfoLevel: %d\n"), lpLocalPath, dwInfoLevel));
  1185. if (dwInfoLevel != UNIVERSAL_NAME_INFO_LEVEL &&
  1186. dwInfoLevel != REMOTE_NAME_INFO_LEVEL)
  1187. {
  1188. DbgP((TEXT("NPGetUniversalName: bad dwInfoLevel value: %d\n"), dwInfoLevel));
  1189. return WN_BAD_LEVEL;
  1190. }
  1191. lstrcpynW(LocalPath, lpLocalPath, MAX_PATH);
  1192. pDriveLetter = LocalPath;
  1193. if (pRemainingPath = wcschr(pDriveLetter, L':'))
  1194. {
  1195. ReplacedChar = *(++pRemainingPath);
  1196. *pRemainingPath = L'\0';
  1197. }
  1198. RemoteNameLength = MAX_PATH;
  1199. if ((dwStatus = NPGetConnection(pDriveLetter, RemoteName, &RemoteNameLength)) != WN_SUCCESS)
  1200. {
  1201. DbgP((TEXT("NPGetUniversalName: NPGetConnection return dwStatus: %d\n"), dwStatus));
  1202. return dwStatus;
  1203. }
  1204. if (pRemainingPath)
  1205. {
  1206. *pRemainingPath = ReplacedChar;
  1207. }
  1208. DbgP((TEXT("NPGetUniversalName: pRemainingPath: %S RemoteName: %S\n"), pRemainingPath, RemoteName));
  1209. lstrcpynW(UniversalName, RemoteName, MAX_PATH);
  1210. if (pRemainingPath)
  1211. {
  1212. wcsncat(UniversalName, pRemainingPath, MAX_PATH - RemoteNameLength/sizeof(WCHAR) - 1);
  1213. UniversalName[MAX_PATH-1] = L'\0';
  1214. }
  1215. DbgP((TEXT("NPGetUniversalName: UniversalName: %S\n"), UniversalName));
  1216. // Determine if the provided buffer is large enough.
  1217. UniversalNameLength = (wcslen(UniversalName) + 1) * sizeof(WCHAR);
  1218. BufferRequired = UniversalNameLength;
  1219. if (dwInfoLevel == UNIVERSAL_NAME_INFO_LEVEL)
  1220. {
  1221. BufferRequired += sizeof(UNIVERSAL_NAME_INFO);
  1222. }
  1223. else
  1224. {
  1225. RemoteNameLength = (wcslen(RemoteName) + 1) * sizeof(WCHAR);
  1226. BufferRequired += sizeof(REMOTE_NAME_INFO) + RemoteNameLength;
  1227. if (pRemainingPath)
  1228. {
  1229. RemainingPathLength = (wcslen(pRemainingPath) + 1) * sizeof(WCHAR);
  1230. BufferRequired += RemainingPathLength;
  1231. }
  1232. }
  1233. if (*lpBufferSize < BufferRequired)
  1234. {
  1235. DbgP((TEXT("NPGetUniversalName: WN_MORE_DATA BufferRequired: %d\n"), BufferRequired));
  1236. *lpBufferSize = BufferRequired;
  1237. return WN_MORE_DATA;
  1238. }
  1239. if (dwInfoLevel == UNIVERSAL_NAME_INFO_LEVEL)
  1240. {
  1241. LPUNIVERSAL_NAME_INFOW pUniversalNameInfo;
  1242. pUniversalNameInfo = (LPUNIVERSAL_NAME_INFOW)lpBuffer;
  1243. pUniversalNameInfo->lpUniversalName = (PWCHAR)((PBYTE)lpBuffer + sizeof(UNIVERSAL_NAME_INFOW));
  1244. CopyMemory( pUniversalNameInfo->lpUniversalName,
  1245. UniversalName,
  1246. UniversalNameLength);
  1247. }
  1248. else
  1249. {
  1250. LPREMOTE_NAME_INFOW pRemoteNameInfo;
  1251. pRemoteNameInfo = (LPREMOTE_NAME_INFOW)lpBuffer;
  1252. pRemoteNameInfo->lpUniversalName = (PWCHAR)((PBYTE)lpBuffer + sizeof(REMOTE_NAME_INFOW));
  1253. pRemoteNameInfo->lpConnectionName = pRemoteNameInfo->lpUniversalName + UniversalNameLength;
  1254. pRemoteNameInfo->lpRemainingPath = pRemoteNameInfo->lpConnectionName + RemoteNameLength;
  1255. CopyMemory( pRemoteNameInfo->lpUniversalName,
  1256. UniversalName,
  1257. UniversalNameLength);
  1258. CopyMemory( pRemoteNameInfo->lpConnectionName,
  1259. RemoteName,
  1260. RemoteNameLength);
  1261. CopyMemory( pRemoteNameInfo->lpRemainingPath,
  1262. pRemainingPath,
  1263. RemainingPathLength);
  1264. }
  1265. DbgP((TEXT("NPGetUniversalName: WN_SUCCESS\n")));
  1266. return WN_SUCCESS;
  1267. }
  1268. int _cdecl _vsnwprintf( wchar_t *buffer, size_t count, wchar_t *format, va_list arg_ptr);
  1269. // Format and write debug information to OutputDebugString
  1270. ULONG
  1271. _cdecl
  1272. DbgPrint(
  1273. LPTSTR Format,
  1274. ...
  1275. )
  1276. {
  1277. ULONG rc = 0;
  1278. TCHAR szbuffer[256];
  1279. va_list marker;
  1280. va_start( marker, Format );
  1281. {
  1282. rc = _vsnwprintf( szbuffer, 254, Format, marker );
  1283. szbuffer[255] = (TCHAR)0;
  1284. OutputDebugString( TRACE_TAG );
  1285. OutputDebugString( szbuffer );
  1286. }
  1287. return rc;
  1288. }