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.

357 lines
11 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. XlateSvc.c
  5. Abstract:
  6. This module contains NetpTranslateServiceName().
  7. Author:
  8. John Rogers (JohnRo) 08-May-1992
  9. Environment:
  10. Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
  11. Requires ANSI C extensions: slash-slash comments, long external names.
  12. Notes:
  13. This code assumes that the info levels are subsets of each other.
  14. Revision History:
  15. 08-May-1992 JohnRo
  16. Created.
  17. 10-May-1992 JohnRo
  18. Added debug output to translate service name routine.
  19. 06-Aug-1992 JohnRo
  20. RAID 3021: NetService APIs don't always translate svc names.
  21. --*/
  22. // These must be included first:
  23. #include <windef.h> // IN, DWORD, etc.
  24. #include <lmcons.h> // NET_API_STATUS.
  25. // These may be included in any order:
  26. #include <debuglib.h> // IF_DEBUG().
  27. #include <lmapibuf.h> // NetApiBufferAllocate(), etc.
  28. #include <lmsname.h> // SERVICE_ and SERVICE_LM20_ equates.
  29. #include <lmsvc.h> // LPSERVER_INFO_2, etc.
  30. #include <netdebug.h> // NetpKdPrint(()), FORMAT_ equates.
  31. #include <netlib.h> // My prototypes, NetpIsServiceLevelValid().
  32. #include <prefix.h> // PREFIX_ equates.
  33. #include <strucinf.h> // NetpServiceStructureInfo().
  34. #include <tstr.h> // TCHAR_EOS.
  35. #include <winerror.h> // NO_ERROR and ERROR_ equates.
  36. NET_API_STATUS
  37. NetpTranslateNamesInServiceArray(
  38. IN DWORD Level,
  39. IN LPVOID OldArrayBase,
  40. IN DWORD EntryCount,
  41. IN BOOL PreferNewStyle,
  42. OUT LPVOID * FinalArrayBase
  43. )
  44. {
  45. NET_API_STATUS ApiStatus;
  46. DWORD EntryIndex;
  47. DWORD FixedSize;
  48. DWORD MaxSize;
  49. LPVOID NewArrayBase = NULL;
  50. LPVOID NewEntry;
  51. LPTSTR NewStringTop;
  52. LPVOID OldEntry;
  53. // Check for GP fault and make error handling easier.
  54. if (FinalArrayBase != NULL) {
  55. *FinalArrayBase = NULL;
  56. }
  57. // Check for caller errors.
  58. if ( !NetpIsServiceLevelValid( Level ) ) {
  59. return (ERROR_INVALID_LEVEL);
  60. } else if (OldArrayBase == NULL) {
  61. return (ERROR_INVALID_PARAMETER);
  62. } else if (FinalArrayBase == NULL) {
  63. return (ERROR_INVALID_PARAMETER);
  64. }
  65. if (EntryCount == 0) {
  66. return(NO_ERROR);
  67. }
  68. ApiStatus = NetpServiceStructureInfo (
  69. Level,
  70. PARMNUM_ALL,
  71. TRUE, // yes, we want native sizes
  72. NULL, // don't need DataDesc16
  73. NULL, // don't need DataDesc32
  74. NULL, // don't need DataDescSmb
  75. & MaxSize, // max entry size in bytes
  76. & FixedSize, // need fixed entry size (in bytes)
  77. NULL ); // don't need StringSize
  78. NetpAssert( ApiStatus == NO_ERROR ); // already checked Level.
  79. NetpAssert( (FixedSize > 0) && (MaxSize > 0) );
  80. //
  81. // Allocate the new array.
  82. //
  83. ApiStatus = NetApiBufferAllocate(
  84. EntryCount * MaxSize, // byte count
  85. (LPVOID *) (LPVOID) & NewArrayBase ); // alloc'ed area
  86. if (ApiStatus != NO_ERROR) {
  87. return (ApiStatus);
  88. }
  89. NetpAssert( NewArrayBase != NULL );
  90. //
  91. // Set up things for the usual string copy scenario.
  92. //
  93. NewStringTop = (LPTSTR) NetpPointerPlusSomeBytes(
  94. NewArrayBase,
  95. EntryCount * MaxSize);
  96. #define COPY_OPTIONAL_STRING( OutField, InString ) \
  97. { \
  98. NetpAssert( NewStruct != NULL); \
  99. if ( (InString) == NULL ) { \
  100. NewStruct->OutField = NULL; \
  101. } else { \
  102. COPY_REQUIRED_STRING( OutField, InString ); \
  103. } \
  104. }
  105. #define COPY_REQUIRED_STRING( OutField, InString ) \
  106. { \
  107. BOOL CopyOK; \
  108. NetpAssert( NewStruct != NULL); \
  109. NetpAssert( InString != NULL); \
  110. CopyOK = NetpCopyStringToBuffer ( \
  111. InString, \
  112. STRLEN(InString), \
  113. NewFixedEnd, \
  114. & NewStringTop, \
  115. & NewStruct->OutField); \
  116. NetpAssert(CopyOK); \
  117. }
  118. //
  119. // Copy the array, translating names while we're at it.
  120. //
  121. NewEntry = NewArrayBase;
  122. OldEntry = OldArrayBase;
  123. for (EntryIndex=0; EntryIndex < EntryCount; ++EntryIndex) {
  124. LPTSTR NewName = NULL;
  125. // These variables are used by the COPY_REQUIRED_STRING and
  126. // COPY_OPTIONAL_STRING macros.
  127. LPSERVICE_INFO_2 NewStruct = NewEntry;
  128. LPSERVICE_INFO_2 OldStruct = OldEntry;
  129. LPBYTE NewFixedEnd = NetpPointerPlusSomeBytes(NewEntry, FixedSize);
  130. ApiStatus = NetpTranslateServiceName(
  131. OldStruct->svci2_name,
  132. PreferNewStyle,
  133. & NewName );
  134. if (ApiStatus != NO_ERROR) {
  135. goto Cleanup;
  136. }
  137. NetpAssert( NewName != NULL );
  138. COPY_REQUIRED_STRING( svci2_name, NewName );
  139. NetpAssert( (NewStruct->svci2_name) != NULL );
  140. if (Level > 0) {
  141. NewStruct->svci2_status = OldStruct->svci2_status;
  142. NewStruct->svci2_code = OldStruct->svci2_code ;
  143. NewStruct->svci2_pid = OldStruct->svci2_pid ;
  144. }
  145. if (Level > 1) {
  146. COPY_OPTIONAL_STRING( svci2_text, OldStruct->svci2_text );
  147. COPY_REQUIRED_STRING(svci2_display_name,OldStruct->svci2_display_name );
  148. //
  149. // Since this routine is used by NT and downlevel NetService wrappers
  150. // we cannot just write a default values in the specific_error field.
  151. //
  152. if ((unsigned short) OldStruct->svci2_code != ERROR_SERVICE_SPECIFIC_ERROR) {
  153. NewStruct->svci2_specific_error = 0;
  154. }
  155. else {
  156. NewStruct->svci2_specific_error = OldStruct->svci2_specific_error;
  157. }
  158. }
  159. NewEntry =
  160. NetpPointerPlusSomeBytes( NewEntry, FixedSize );
  161. OldEntry =
  162. NetpPointerPlusSomeBytes( OldEntry, FixedSize );
  163. }
  164. ApiStatus = NO_ERROR;
  165. Cleanup:
  166. if (ApiStatus != NO_ERROR) {
  167. if (NewArrayBase != NULL) {
  168. (VOID) NetApiBufferFree( NewArrayBase );
  169. }
  170. NetpAssert( (*FinalArrayBase) == NULL );
  171. } else {
  172. *FinalArrayBase = NewArrayBase;
  173. }
  174. return (ApiStatus);
  175. } // NetpTranslateNamesInServiceArray
  176. NET_API_STATUS
  177. NetpTranslateServiceName(
  178. IN LPTSTR GivenServiceName,
  179. IN BOOL PreferNewStyle,
  180. OUT LPTSTR * TranslatedName
  181. )
  182. /*++
  183. Routine Description:
  184. This routine attempts to translate a given service name to
  185. an old-style (as used by downlevel Lanman machines) or new-style
  186. (as used by NT machines) name. For instance, "WORKSTATION" might
  187. become "LanmanWorkstation", or vice versa. This routine is used in
  188. remoting NetService APIs in three different flavors:
  189. - NT-to-NT (prefer a new-style name)
  190. - NT-to-downlevel (prefer an old-style name)
  191. - downlevel-to-NT (prefer a new-style name)
  192. Arguments:
  193. GivenServiceName - Supplies the number of strings specified in ArgsArray.
  194. PreferNewStyle - Indicates whether the call prefers a new-style name
  195. (for use on an NT system) as opposed to an old-style name (for use
  196. on a downlevel LanMan system).
  197. TranslatedName - This pointer will be set to one of the following:
  198. - a static (constant) string with the translated service name.
  199. - GivenServiceName if the service name is not recognized. (This
  200. may be the case for nonstandard Lanman services, and is not considered
  201. an error by this routine.)
  202. - NULL if an error occurs.
  203. Return Value:
  204. NET_API_STATUS - NO_ERROR or ERROR_INVALID_PARAMETER.
  205. --*/
  206. {
  207. //
  208. // Error check caller.
  209. //
  210. if (TranslatedName == NULL) {
  211. return (ERROR_INVALID_PARAMETER);
  212. } else if (GivenServiceName == NULL) {
  213. *TranslatedName = NULL;
  214. return (ERROR_INVALID_PARAMETER);
  215. } else if ((*GivenServiceName) == TCHAR_EOS) {
  216. *TranslatedName = NULL;
  217. return (ERROR_INVALID_PARAMETER);
  218. }
  219. #define TRY_NAME( NewName, OldName ) \
  220. { \
  221. if (STRICMP(GivenServiceName, OldName)==0 ) { \
  222. if (PreferNewStyle) { \
  223. *TranslatedName = (NewName); \
  224. } else { \
  225. /* Given matches old, except possibly mixed case. */ \
  226. /* Be pessimistic and send upper case only do downlevel. */ \
  227. *TranslatedName = (OldName); \
  228. } \
  229. goto Done; \
  230. } else if (STRICMP(GivenServiceName, NewName)==0 ) { \
  231. if (PreferNewStyle) { \
  232. /* Have choice between given and new name here. */ \
  233. /* New APIs handle mixed case, so preserve callers's case. */ \
  234. *TranslatedName = (GivenServiceName); \
  235. } else { \
  236. *TranslatedName = (OldName); \
  237. } \
  238. goto Done; \
  239. } \
  240. }
  241. //
  242. // Do brute-force comparisons of names
  243. //
  244. // PERFORMANCE NOTE: This list should be in order from
  245. // most-often used to least-often. Note that workstation and
  246. // server are often used as part of remoting APIs, so I
  247. // think they should be first.
  248. TRY_NAME( SERVICE_WORKSTATION, SERVICE_LM20_WORKSTATION );
  249. TRY_NAME( SERVICE_SERVER, SERVICE_LM20_SERVER );
  250. TRY_NAME( SERVICE_BROWSER, SERVICE_LM20_BROWSER );
  251. TRY_NAME( SERVICE_MESSENGER, SERVICE_LM20_MESSENGER );
  252. TRY_NAME( SERVICE_NETRUN, SERVICE_LM20_NETRUN );
  253. TRY_NAME( SERVICE_SPOOLER, SERVICE_LM20_SPOOLER );
  254. TRY_NAME( SERVICE_ALERTER, SERVICE_LM20_ALERTER );
  255. TRY_NAME( SERVICE_NETLOGON, SERVICE_LM20_NETLOGON );
  256. TRY_NAME( SERVICE_NETPOPUP, SERVICE_LM20_NETPOPUP );
  257. TRY_NAME( SERVICE_SQLSERVER, SERVICE_LM20_SQLSERVER );
  258. TRY_NAME( SERVICE_REPL, SERVICE_LM20_REPL );
  259. TRY_NAME( SERVICE_RIPL, SERVICE_LM20_RIPL );
  260. TRY_NAME( SERVICE_TIMESOURCE, SERVICE_LM20_TIMESOURCE );
  261. TRY_NAME( SERVICE_AFP, SERVICE_LM20_AFP );
  262. TRY_NAME( SERVICE_UPS, SERVICE_LM20_UPS );
  263. TRY_NAME( SERVICE_XACTSRV, SERVICE_LM20_XACTSRV );
  264. TRY_NAME( SERVICE_TCPIP, SERVICE_LM20_TCPIP );
  265. //
  266. // No match. Use given name.
  267. //
  268. *TranslatedName = GivenServiceName;
  269. Done:
  270. IF_DEBUG( XLATESVC ) {
  271. NetpKdPrint(( PREFIX_NETLIB "NetpTranslateServiceName: "
  272. " translated " FORMAT_LPTSTR " to " FORMAT_LPTSTR ".\n",
  273. GivenServiceName, *TranslatedName ));
  274. }
  275. return (NO_ERROR);
  276. } // NetpTranslateServiceName