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.

297 lines
10 KiB

  1. /*++
  2. Copyright (c) 1991-92 Microsoft Corporation
  3. Module Name:
  4. Supports.c
  5. Abstract:
  6. This module determines which optional features that a given remote
  7. machine supports. These features are of interest to the RpcXlate
  8. code, among other people.
  9. Author:
  10. John Rogers (JohnRo) 28-Mar-1991
  11. Environment:
  12. Only runs under NT, although the interface is portable (Win/32).
  13. Requires ANSI C extensions: slash-slash comments, long external names.
  14. Revision History:
  15. 28-Mar-1991 Johnro
  16. Created.
  17. 02-Apr-1991 JohnRo
  18. Moved NetpRdrFsControlTree to <netlibnt.h>.
  19. 06-May-1991 JohnRo
  20. Implement UNICODE.
  21. 26-Jul-1991 JohnRo
  22. Quiet DLL stub debug output.
  23. 31-Oct-1991 JohnRo
  24. RAID 3414: allow explicit local server name.
  25. Also allow use of NetRemoteComputerSupports() for local computer.
  26. Minor UNICODE work.
  27. 08-May-1992 JohnRo
  28. Use <prefix.h> equates.
  29. 22-Sep-1992 JohnRo
  30. RAID 6739: Browser too slow when not logged into browsed domain.
  31. --*/
  32. // These must be included first:
  33. #include <nt.h> // IN, NULL, etc.
  34. #include <windef.h> // DWORD, LPDWORD, LPTSTR, TCHAR, etc.
  35. #include <lmcons.h> // NET_API_STATUS, NET_API_FUNCTION.
  36. // These may be included in any order:
  37. #include <debuglib.h> // IF_DEBUG().
  38. #include <icanon.h> // NetpIsRemote(), NIRFLAG_ stuff, IS equates.
  39. #include <lmerr.h> // NERR_Success, etc.
  40. #include <lmremutl.h> // My prototype, SUPPORTS_ equates.
  41. #include <names.h> // NetpIsRemoteNameValid().
  42. #include <netdebug.h> // NetpAssert().
  43. #include <netlib.h> // NetpMemoryAllocate(), NetpMemoryFree().
  44. #include <netlibnt.h> // NetpRdrFsControlTree().
  45. #include <ntddnfs.h> // LMR_TRANSACTION, etc.
  46. #include <prefix.h> // PREFIX_ equates.
  47. #include <tstring.h> // STRCAT(), STRCPY(), STRLEN().
  48. #include <lmuse.h> // USE_IPC
  49. NET_API_STATUS NET_API_FUNCTION
  50. NetRemoteComputerSupports(
  51. IN LPCWSTR UncServerName OPTIONAL, // Must start with "\\".
  52. IN DWORD OptionsWanted, // Set SUPPORT_ bits wanted.
  53. OUT LPDWORD OptionsSupported // Supported features, masked.
  54. )
  55. #define SHARE_SUFFIX (LPTSTR) TEXT("\\IPC$")
  56. #define SHARE_SUFFIX_LEN 5
  57. #ifdef UNICODE
  58. #define LOCAL_FLAGS ( SUPPORTS_REMOTE_ADMIN_PROTOCOL \
  59. | SUPPORTS_RPC \
  60. | SUPPORTS_SAM_PROTOCOL \
  61. | SUPPORTS_UNICODE \
  62. | SUPPORTS_LOCAL )
  63. #else // not UNICODE
  64. #define LOCAL_FLAGS ( SUPPORTS_REMOTE_ADMIN_PROTOCOL \
  65. | SUPPORTS_RPC \
  66. | SUPPORTS_SAM_PROTOCOL \
  67. | SUPPORTS_LOCAL )
  68. #endif // not UNICODE
  69. /*++
  70. Routine Description:
  71. NetRemoteComputerSupports queries the redirector about a given remote
  72. system. This is done to find out which optional features the remote
  73. system supports. The features of interest are Unicode, RPC, and the
  74. Remote Admin Protocol.
  75. This will establish a connection if one doesn't already exist.
  76. Arguments:
  77. UncServerName - Gives name of remote server to query. This must begin
  78. with "\\".
  79. OptionsWanted - Gives a set of bits indicating which features the caller is
  80. interested in. (At least one bit must be on.)
  81. OptionsSupported - Points to a DWORD which will be set with set of bits
  82. indicating which of the features selected by OptionsWanted are actually
  83. implemented on the computer with UncServerName. (All other bits in this
  84. DWORD will be set to 0.) The value of OptionsSupported is undefined if
  85. the return value is not NERR_Success.
  86. Return Value:
  87. NET_API_STATUS.
  88. --*/
  89. {
  90. NET_API_STATUS Status;
  91. DWORD TempSupported = 0;
  92. IF_DEBUG(SUPPORTS) {
  93. NetpKdPrint(( PREFIX_NETAPI "NetRemoteComputerSupports: input mask is "
  94. FORMAT_HEX_DWORD ".\n", OptionsWanted));
  95. }
  96. // Error check what caller gave us.
  97. if (OptionsSupported == NULL) {
  98. return (ERROR_INVALID_PARAMETER);
  99. } else if (OptionsWanted == 0) {
  100. // Not what caller really intended, probably.
  101. return (ERROR_INVALID_PARAMETER);
  102. }
  103. //
  104. // Handle no name given (implies local computer).
  105. //
  106. if ( (UncServerName==NULL) || ((*UncServerName) == (TCHAR) '\0') ) {
  107. TempSupported = LOCAL_FLAGS & OptionsWanted;
  108. } else {
  109. TCHAR CanonServerName[MAX_PATH];
  110. DWORD LocalOrRemote; // Will be set to ISLOCAL or ISREMOTE.
  111. //
  112. // Name was given. Canonicalize it and check if it's remote.
  113. //
  114. Status = NetpIsRemote(
  115. (LPWSTR)UncServerName, // input: uncanon name
  116. & LocalOrRemote, // output: local or remote flag
  117. CanonServerName, // output: canon name
  118. 0); // flags: normal
  119. IF_DEBUG(SUPPORTS) {
  120. NetpKdPrint(( PREFIX_NETAPI
  121. "NetRemoteComputerSupports: canon status is "
  122. FORMAT_API_STATUS ", Lcl/rmt=" FORMAT_HEX_DWORD
  123. ", canon buf is '" FORMAT_LPTSTR "'.\n",
  124. Status, LocalOrRemote, CanonServerName));
  125. }
  126. if (Status != NERR_Success) {
  127. return (Status);
  128. }
  129. if (LocalOrRemote == ISLOCAL) {
  130. //
  131. // Explicit local name given.
  132. //
  133. TempSupported = LOCAL_FLAGS & OptionsWanted;
  134. } else {
  135. //
  136. // Explicit remote name given.
  137. //
  138. DWORD RedirCapabilities;
  139. PLMR_CONNECTION_INFO_2 RedirConnInfo;
  140. DWORD RedirConnInfoSize = sizeof(LMR_CONNECTION_INFO_2)
  141. + ( (MAX_PATH+1 + MAX_PATH+1) * sizeof(TCHAR) );
  142. PLMR_REQUEST_PACKET RedirRequest;
  143. DWORD RedirRequestSize = sizeof(LMR_REQUEST_PACKET);
  144. LPTSTR TreeConnName;
  145. // Build tree connect name.
  146. TreeConnName =
  147. NetpMemoryAllocate(
  148. (STRLEN(CanonServerName) + SHARE_SUFFIX_LEN + 1)
  149. * sizeof(TCHAR) );
  150. if (TreeConnName == NULL) {
  151. return (ERROR_NOT_ENOUGH_MEMORY);
  152. }
  153. (void) STRCPY(TreeConnName, CanonServerName);
  154. (void) STRCAT(TreeConnName, SHARE_SUFFIX);
  155. NetpAssert(NetpIsRemoteNameValid(TreeConnName));
  156. // Alloc fsctl buffers.
  157. RedirConnInfo = NetpMemoryAllocate(RedirConnInfoSize);
  158. if (RedirConnInfo == NULL) {
  159. NetpMemoryFree(TreeConnName);
  160. return (ERROR_NOT_ENOUGH_MEMORY);
  161. }
  162. RedirRequest = NetpMemoryAllocate(RedirRequestSize);
  163. if (RedirRequest == NULL) {
  164. NetpMemoryFree(RedirConnInfo);
  165. NetpMemoryFree(TreeConnName);
  166. return (ERROR_NOT_ENOUGH_MEMORY);
  167. }
  168. RedirRequest->Level = 2;
  169. RedirRequest->Type = GetConnectionInfo;
  170. RedirRequest->Version = REQUEST_PACKET_VERSION;
  171. // Open tree conn (which will establish connection with the remote
  172. // server if one doesn't already exist) and do the FSCTL.
  173. Status = NetpRdrFsControlTree(
  174. TreeConnName, // \\server\IPC$
  175. NULL, // No transport.
  176. USE_IPC, // Connection type
  177. FSCTL_LMR_GET_CONNECTION_INFO, // fsctl func code
  178. NULL, // security descriptor
  179. RedirRequest, // in buffer
  180. RedirRequestSize, // in buffer size
  181. RedirConnInfo, // out buffer
  182. RedirConnInfoSize, // out buffer size
  183. FALSE); // not a "null session" API.
  184. IF_DEBUG(SUPPORTS) {
  185. NetpKdPrint(( PREFIX_NETAPI
  186. "NetRemoteComputerSupports: back from fsctl, "
  187. "status is " FORMAT_API_STATUS ".\n", Status));
  188. }
  189. // Handle remote machine not found.
  190. if (Status != NERR_Success) {
  191. NetpMemoryFree(RedirConnInfo);
  192. NetpMemoryFree(RedirRequest);
  193. NetpMemoryFree(TreeConnName);
  194. return (Status);
  195. }
  196. RedirCapabilities = RedirConnInfo->Capabilities;
  197. IF_DEBUG(SUPPORTS) {
  198. NetpKdPrint(( PREFIX_NETAPI
  199. "NetRemoteComputerSupports: redir mask is "
  200. FORMAT_HEX_DWORD ".\n", RedirCapabilities));
  201. }
  202. NetpMemoryFree(RedirConnInfo);
  203. NetpMemoryFree(RedirRequest);
  204. NetpMemoryFree(TreeConnName);
  205. if (OptionsWanted & SUPPORTS_REMOTE_ADMIN_PROTOCOL) {
  206. if (RedirCapabilities & CAPABILITY_REMOTE_ADMIN_PROTOCOL) {
  207. TempSupported |= SUPPORTS_REMOTE_ADMIN_PROTOCOL;
  208. }
  209. }
  210. if (OptionsWanted & SUPPORTS_RPC) {
  211. if (RedirCapabilities & CAPABILITY_RPC) {
  212. TempSupported |= SUPPORTS_RPC;
  213. }
  214. }
  215. if (OptionsWanted & SUPPORTS_SAM_PROTOCOL) {
  216. if (RedirCapabilities & CAPABILITY_SAM_PROTOCOL) {
  217. TempSupported |= SUPPORTS_SAM_PROTOCOL;
  218. }
  219. }
  220. if (OptionsWanted & SUPPORTS_UNICODE) {
  221. if (RedirCapabilities & CAPABILITY_UNICODE) {
  222. TempSupported |= SUPPORTS_UNICODE;
  223. }
  224. }
  225. }
  226. }
  227. IF_DEBUG(SUPPORTS) {
  228. NetpKdPrint(( PREFIX_NETAPI "NetRemoteComputerSupports: output mask is "
  229. FORMAT_HEX_DWORD ".\n", TempSupported));
  230. }
  231. // Make sure we don't tell caller anything he/she didn't want to know.
  232. NetpAssert( (TempSupported & (~OptionsWanted)) == 0);
  233. // Tell caller what we know.
  234. *OptionsSupported = TempSupported;
  235. return (NERR_Success);
  236. } // NetRemoteComputerSupports