Windows NT 4.0 source code leak
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.

436 lines
13 KiB

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