Source code of Windows XP (NT5)
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.

462 lines
14 KiB

  1. /*++
  2. Copyright (c) 1991-1993 Microsoft Corporation
  3. Module Name:
  4. UNINAME.CXX
  5. Abstract:
  6. Author:
  7. Dan Lafferty (danl) 24-Apr-1994
  8. Environment:
  9. User Mode -Win32
  10. Revision History:
  11. 24-Apr-1994 danl
  12. Created
  13. 05-May-1999 jschwart
  14. Make provider addition/removal dynamic
  15. --*/
  16. //
  17. // INCLUDES
  18. //
  19. #include "precomp.hxx"
  20. #include <tstr.h> // STRLEN
  21. //
  22. // PROTOTYPES
  23. //
  24. DWORD
  25. MprTranslateRemoteName(
  26. LPREMOTE_NAME_INFOW pRemoteNameInfo,
  27. LPDWORD lpBufferSize,
  28. LPWSTR pRemoteName,
  29. LPCWSTR pRemainingPath
  30. );
  31. DWORD
  32. WNetGetUniversalNameW (
  33. IN LPCTSTR lpLocalPath,
  34. IN DWORD dwInfoLevel,
  35. OUT LPVOID lpBuffer,
  36. IN OUT LPDWORD lpBufferSize
  37. )
  38. /*++
  39. Routine Description:
  40. Arguments:
  41. lpLocalPath - This is a pointer to the string that contains the local path.
  42. This is a path that contains a drive-letter prefixed path string.
  43. "X:" is a valid local path. "X:\nt\system32" is a valid local path.
  44. "\\popcorn\public\nt" is not a valid local path.
  45. dwInfoLevel - This DWORD indicates what information is to be stored in
  46. the return buffer. Currently the following levels are supported:
  47. INFOLEVEL_UNIVERSAL_NAME
  48. INFOLEVEL_REMOTE_NAME
  49. lpBuffer - This is a pointer to the buffer where the requested information
  50. is to be placed.
  51. lpBufferSize - This is a pointer to the size of the buffer in bytes.
  52. If the buffer is not large enough, then the required buffer size
  53. Will be placed in this location upon return with WN_MORE_DATA.
  54. Return Value:
  55. --*/
  56. {
  57. DWORD status = WN_SUCCESS;
  58. LPDWORD indexArray;
  59. DWORD localArray[DEFAULT_MAX_PROVIDERS];
  60. DWORD numProviders;
  61. LPPROVIDER provider;
  62. DWORD statusFlag = 0; // used to indicate major error types
  63. BOOL fcnSupported = FALSE; // Is fcn supported by a provider?
  64. DWORD i;
  65. WCHAR pDriveLetter[4];
  66. LPWSTR pRemoteName = (LPWSTR)((LPBYTE)lpBuffer + sizeof(REMOTE_NAME_INFOW));
  67. //
  68. // Validate the drive portion of the local path. Make sure its a valid
  69. // device.
  70. //
  71. __try {
  72. pDriveLetter[0] = lpLocalPath[0];
  73. pDriveLetter[1] = lpLocalPath[1];
  74. pDriveLetter[2] = L'\0';
  75. if (MprDeviceType(pDriveLetter) != REDIR_DEVICE) {
  76. status = WN_BAD_LOCALNAME;
  77. }
  78. }
  79. __except(EXCEPTION_EXECUTE_HANDLER) {
  80. status = GetExceptionCode();
  81. if (status != EXCEPTION_ACCESS_VIOLATION) {
  82. MPR_LOG(ERROR,"WNetGetUniversalNameW:Unexpected Exception 0x%lx\n",status);
  83. }
  84. status = WN_BAD_POINTER;
  85. }
  86. if (status != WN_SUCCESS) {
  87. SetLastError(status);
  88. return(status);
  89. }
  90. if ((dwInfoLevel != UNIVERSAL_NAME_INFO_LEVEL) &&
  91. (dwInfoLevel != REMOTE_NAME_INFO_LEVEL)) {
  92. SetLastError(ERROR_INVALID_LEVEL);
  93. return(ERROR_INVALID_LEVEL);
  94. }
  95. MprCheckProviders();
  96. CProviderSharedLock PLock;
  97. //
  98. // Check to see if this is a remote drive to begin with. If not, we can
  99. // fail it quickly.
  100. //
  101. pDriveLetter[2] = L'\\';
  102. pDriveLetter[3] = L'\0';
  103. if (GetDriveType(pDriveLetter) != DRIVE_REMOTE) {
  104. status = WN_NOT_CONNECTED;
  105. }
  106. pDriveLetter[2] = L'\0';
  107. if (status == WN_SUCCESS) {
  108. INIT_IF_NECESSARY(NETWORK_LEVEL,status);
  109. //
  110. // Find the list of providers to call for this request.
  111. //
  112. indexArray = localArray;
  113. status = MprFindCallOrder(
  114. NULL,
  115. &indexArray,
  116. &numProviders,
  117. NETWORK_TYPE);
  118. if (status != WN_SUCCESS) {
  119. SetLastError(status);
  120. return(status);
  121. }
  122. //
  123. // Loop through the list of providers until one answers the request,
  124. // or the list is exhausted.
  125. //
  126. for (i=0; i<numProviders; i++) {
  127. //
  128. // Call the appropriate providers API entry point
  129. // If the provider doesn't support GetUniversalName
  130. // then see if that provider owns the connection by
  131. // calling GetConnection.
  132. //
  133. provider = GlobalProviderInfo + indexArray[i];
  134. if (provider->GetUniversalName != NULL) {
  135. //--------------------------------------
  136. // Call Provider with GetUniversalName
  137. //--------------------------------------
  138. fcnSupported = TRUE;
  139. __try {
  140. status = provider->GetUniversalName(
  141. lpLocalPath,
  142. dwInfoLevel,
  143. lpBuffer,
  144. lpBufferSize);
  145. }
  146. __except(EXCEPTION_EXECUTE_HANDLER) {
  147. status = GetExceptionCode();
  148. if (status != EXCEPTION_ACCESS_VIOLATION) {
  149. MPR_LOG(ERROR,"WNetGetUniversalNameW:Unexpected Exception 0x%lx\n",status);
  150. }
  151. status = WN_BAD_POINTER;
  152. }
  153. }
  154. //
  155. // Try GetConnection for a Remote name. Note that we
  156. // don't do this for a Universal name since providers
  157. // are not required to support it (i.e., the name in
  158. // the registry might not be universal).
  159. //
  160. else if ((dwInfoLevel == REMOTE_NAME_INFO_LEVEL) &&
  161. (provider->GetConnection != NULL)) {
  162. //--------------------------------------
  163. // Call Provider with GetConnection
  164. //--------------------------------------
  165. DWORD buflen = 0;
  166. __try {
  167. if (*lpBufferSize > sizeof(REMOTE_NAME_INFOW)) {
  168. //
  169. // Remember, GetConnection is looking for the size of the
  170. // buffer in characters - not bytes.
  171. //
  172. buflen = ((*lpBufferSize) - sizeof(REMOTE_NAME_INFOW))/sizeof(WCHAR);
  173. }
  174. status = provider->GetConnection(
  175. pDriveLetter,
  176. pRemoteName,
  177. &buflen
  178. );
  179. if (status == WN_SUCCESS) {
  180. //
  181. // We got the RemoteName. See if there's enough room
  182. // in the buffer for the portion of the local path that
  183. // follows the drive letter and colon. If there's
  184. // enough room, then store the remaining path in the
  185. // buffer and fill in the structure.
  186. //
  187. status = MprTranslateRemoteName(
  188. (LPREMOTE_NAME_INFOW)lpBuffer,
  189. lpBufferSize,
  190. pRemoteName,
  191. &(lpLocalPath[2]));
  192. fcnSupported = TRUE;
  193. }
  194. else if (status == WN_MORE_DATA) {
  195. //
  196. // The buflen we get back from GetConnection will account
  197. // for the RemoteName portion, but not the remaining path
  198. // portion. So we have to add that to the size calculation.
  199. //
  200. *lpBufferSize = sizeof(REMOTE_NAME_INFOW) +
  201. (WCSSIZE(&(lpLocalPath[2]))) +
  202. (buflen * sizeof(WCHAR));
  203. fcnSupported = TRUE;
  204. }
  205. }
  206. __except(EXCEPTION_EXECUTE_HANDLER) {
  207. status = GetExceptionCode();
  208. if (status != EXCEPTION_ACCESS_VIOLATION) {
  209. MPR_LOG(ERROR,"WNetGetUniversalNameW:Unexpected Exception 0x%lx\n",status);
  210. }
  211. status = WN_BAD_POINTER;
  212. }
  213. }
  214. else {
  215. //----------------------------------
  216. // NEITHER FUNCTION IS SUPPORTED!
  217. // Go to the next provider.
  218. //----------------------------------
  219. continue;
  220. }
  221. if (status == WN_NO_NETWORK) {
  222. statusFlag |= NO_NET;
  223. }
  224. else if ((status == WN_NOT_CONNECTED) ||
  225. (status == WN_BAD_LOCALNAME)){
  226. //
  227. // WN_NOT_CONNECTED means that lpLocalPath is not a
  228. // redirected device for this provider.
  229. //
  230. statusFlag |= BAD_NAME;
  231. }
  232. else {
  233. //
  234. // If it wasn't one of those errors, then the provider
  235. // must have accepted responsiblity for the request.
  236. // so we exit and process the results. Note that the
  237. // statusFlag is cleared because we want to ignore other
  238. // error information that we gathered up until now.
  239. //
  240. statusFlag = 0;
  241. break;
  242. }
  243. } // End for each provider.
  244. if (fcnSupported == FALSE) {
  245. //
  246. // No providers in the list support the API function. Therefore,
  247. // we assume that no networks are installed.
  248. //
  249. status = WN_NOT_SUPPORTED;
  250. }
  251. //
  252. // If memory was allocated by MprFindCallOrder, free it.
  253. //
  254. if (indexArray != localArray) {
  255. LocalFree(indexArray);
  256. }
  257. //
  258. // Handle special errors.
  259. //
  260. if (statusFlag == (NO_NET | BAD_NAME)) {
  261. //
  262. // Check to see if there was a mix of special errors that occured.
  263. // If so, pass back the combined error message. Otherwise, let the
  264. // last error returned get passed back.
  265. //
  266. status = WN_NO_NET_OR_BAD_PATH;
  267. }
  268. }
  269. //
  270. // Handle normal errors passed back from the provider
  271. //
  272. // NOTE: INIT_IF_NECESSARY may not have been executed by this point.
  273. // Use caution when modifying code below. For example, this affects
  274. // the behavior of MprGetRemoteName.
  275. //
  276. if (status != WN_SUCCESS)
  277. {
  278. if (status == WN_NOT_CONNECTED
  279. &&
  280. dwInfoLevel == REMOTE_NAME_INFO_LEVEL)
  281. {
  282. DWORD bufSize;
  283. //
  284. // If not connected, but there is an entry for the LocalName
  285. // in the registry, then return the remote name that was stored
  286. // with it. Note that we don't do this for a Universal name
  287. // since providers are not required to support it (i.e., the
  288. // name in the registry might not be universal).
  289. //
  290. bufSize = *lpBufferSize - sizeof(REMOTE_NAME_INFOW);
  291. if (MprGetRemoteName(
  292. pDriveLetter,
  293. &bufSize,
  294. pRemoteName,
  295. &status)) {
  296. if (status == WN_SUCCESS)
  297. {
  298. status = MprTranslateRemoteName(
  299. (LPREMOTE_NAME_INFOW)lpBuffer,
  300. lpBufferSize,
  301. pRemoteName,
  302. &(lpLocalPath[2]));
  303. if (status == WN_SUCCESS)
  304. {
  305. status = WN_CONNECTION_CLOSED;
  306. }
  307. }
  308. }
  309. }
  310. SetLastError(status);
  311. }
  312. return(status);
  313. }
  314. DWORD
  315. MprTranslateRemoteName(
  316. LPREMOTE_NAME_INFOW pRemoteNameInfo,
  317. LPDWORD lpBufferSize,
  318. LPWSTR pRemoteName,
  319. LPCWSTR pRemainingPath
  320. )
  321. /*++
  322. Routine Description:
  323. This function adds the remaining path string to the buffer and places
  324. the pointer to it into the structure.
  325. Arguments:
  326. pRemoteNameInfo - Pointer to a buffer which will contain the
  327. REMOTE_NAME_INFO structure followed by the strings pointed
  328. to in the structure.
  329. lpBufferSize - Pointer to a DWORD that indicates the size of the
  330. pRemoteNameInfo buffer.
  331. pRemoteName - Pointer to the location in the pRemoteNameInfo buffer
  332. where the remote name string can be placed.
  333. pRemainingPath - Pointer to the remaining path string.
  334. Return Value:
  335. WN_MORE_DATA - If the buffer was not large enough to hold all the data.
  336. When this is returned, the required buffer size is stored at the
  337. location pointed to by lpBufferSize.
  338. WN_SUCCESS - If the operation was completely successful.
  339. Note:
  340. --*/
  341. {
  342. DWORD bufSize = *lpBufferSize - sizeof(REMOTE_NAME_INFOW);
  343. DWORD remoteNameLen;
  344. DWORD remainingPathLen;
  345. DWORD sizeRequired;
  346. //
  347. // We got the RemoteName. See if there's enough room
  348. // in the buffer for the portion of the local path that
  349. // follows the drive letter and colon. If there's
  350. // enough room, then store the remaining path in the
  351. // buffer and fill in the structure.
  352. //
  353. remoteNameLen = wcslen(pRemoteName);
  354. remainingPathLen = wcslen(pRemainingPath);
  355. sizeRequired = sizeof(REMOTE_NAME_INFOW) +
  356. ((remoteNameLen + remainingPathLen + 2) *
  357. sizeof(WCHAR));
  358. if (*lpBufferSize < sizeRequired) {
  359. *lpBufferSize = sizeRequired;
  360. return(WN_MORE_DATA);
  361. }
  362. else {
  363. pRemoteNameInfo->lpUniversalName = NULL;
  364. pRemoteNameInfo->lpConnectionName = pRemoteName;
  365. pRemoteNameInfo->lpRemainingPath = pRemoteName+remoteNameLen+sizeof(WCHAR);
  366. wcscpy(pRemoteNameInfo->lpRemainingPath, pRemainingPath);
  367. }
  368. return(WN_SUCCESS);
  369. }