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.

481 lines
11 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows NT **/
  3. /** Copyright(c) Microsoft Corp., 1993 **/
  4. /**********************************************************************/
  5. /*
  6. utility.cxx
  7. This module contains routines of general utility.
  8. Functions exported by this module:
  9. TransferType
  10. TransferMode
  11. DisplayBool
  12. IsDecimalNumber
  13. AllocErrorText
  14. FreeErrorText
  15. OpenDosPath
  16. FlipSlashes
  17. OpenLogFile
  18. P_strncpy
  19. ParseUserName
  20. FILE HISTORY:
  21. KeithMo 17-Mar-1993 Created.
  22. */
  23. #include "ftpdp.hxx"
  24. #include <mbstring.h>
  25. extern "C" {
  26. # include <ntlsa.h>
  27. };
  28. //
  29. // Public functions.
  30. //
  31. /*******************************************************************
  32. NAME: TransferType
  33. SYNOPSIS: Generates printable form of a transfer type.
  34. ENTRY: type - From the XFER_TYPE enumerator.
  35. RETURNS: CHAR * - "ASCII", "BINARY", etc.
  36. HISTORY:
  37. KeithMo 12-Mar-1993 Created.
  38. ********************************************************************/
  39. CHAR *
  40. TransferType(
  41. XFER_TYPE type
  42. )
  43. {
  44. CHAR * pszResult = NULL;
  45. switch( type )
  46. {
  47. case XferTypeAscii :
  48. pszResult = "ASCII";
  49. break;
  50. case XferTypeBinary :
  51. pszResult = "BINARY";
  52. break;
  53. default :
  54. DBGPRINTF(( DBG_CONTEXT,
  55. "invalid transfer type %d\n",
  56. type ));
  57. DBG_ASSERT( FALSE );
  58. pszResult = "ASCII";
  59. break;
  60. }
  61. DBG_ASSERT( pszResult != NULL );
  62. return pszResult;
  63. } // TransferType
  64. /*******************************************************************
  65. NAME: TransferMode
  66. SYNOPSIS: Generates printable form of a transfer mode.
  67. ENTRY: mode - From the XFER_MODE enumerator.
  68. RETURNS: CHAR * - "STREAM", "BLOCK", etc.
  69. NOTES: Currently, only the STREAM mode is suppored.
  70. HISTORY:
  71. KeithMo 12-Mar-1993 Created.
  72. ********************************************************************/
  73. CHAR *
  74. TransferMode(
  75. XFER_MODE mode
  76. )
  77. {
  78. CHAR * pszResult = NULL;
  79. switch( mode )
  80. {
  81. case XferModeStream :
  82. pszResult = "STREAM";
  83. break;
  84. case XferModeBlock :
  85. pszResult = "BLOCK";
  86. break;
  87. default :
  88. DBGPRINTF(( DBG_CONTEXT,
  89. "invalid transfer mode %d\n",
  90. mode ));
  91. DBG_ASSERT( FALSE );
  92. pszResult = "STREAM";
  93. break;
  94. }
  95. DBG_ASSERT( pszResult != NULL );
  96. return pszResult;
  97. } // TransferMode
  98. /*******************************************************************
  99. NAME: DisplayBool
  100. SYNOPSIS: Generates printable form of a boolean.
  101. ENTRY: fFlag - The BOOL to display.
  102. RETURNS: CHAR * - "TRUE" or "FALSE".
  103. HISTORY:
  104. KeithMo 17-Mar-1993 Created.
  105. ********************************************************************/
  106. CHAR *
  107. DisplayBool(
  108. BOOL fFlag
  109. )
  110. {
  111. return fFlag ? "TRUE" : "FALSE";
  112. } // DisplayBool
  113. /*******************************************************************
  114. NAME: IsDecimalNumber
  115. SYNOPSIS: Determines if a given string represents a decimal
  116. number.
  117. ENTRY: psz - The string to scan.
  118. RETURNS: BOOL - TRUE if this is a decimal number, FALSE
  119. otherwise.
  120. HISTORY:
  121. KeithMo 12-Mar-1993 Created.
  122. ********************************************************************/
  123. BOOL
  124. IsDecimalNumber(
  125. CHAR * psz
  126. )
  127. {
  128. BOOL fResult = ( *psz != '\0' );
  129. CHAR ch;
  130. while( ch = *psz++ )
  131. {
  132. if( ( ch < '0' ) || ( ch > '9' ) )
  133. {
  134. fResult = FALSE;
  135. break;
  136. }
  137. }
  138. return fResult;
  139. } // IsDecimalNumber
  140. /*******************************************************************
  141. NAME: AllocErrorText
  142. SYNOPSIS: Maps a specified Win32 error code to a textual
  143. description. In the interest of multithreaded
  144. safety, this routine will allocate a block of memory
  145. to contain the text and return a pointer to that
  146. block. It is up to the caller to free the block
  147. with FreeErrorText.
  148. ENTRY: err - The error to map.
  149. RETURNS: CHAR * - A textual description of err. Will be NULL
  150. if an error occurred while mapping err to text.
  151. HISTORY:
  152. KeithMo 27-Apr-1993 Created.
  153. ********************************************************************/
  154. CHAR *
  155. AllocErrorText(
  156. APIERR err
  157. )
  158. {
  159. APIERR fmerr = NO_ERROR;
  160. CHAR * pszText = NULL;
  161. if( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
  162. | FORMAT_MESSAGE_IGNORE_INSERTS
  163. | FORMAT_MESSAGE_FROM_SYSTEM
  164. | FORMAT_MESSAGE_MAX_WIDTH_MASK,
  165. NULL,
  166. (DWORD)err,
  167. g_pInetSvc->IsSystemDBCS() // always use english for
  168. ? 0x409 // FarEast NT system
  169. : 0,
  170. (LPTSTR)&pszText,
  171. 0,
  172. NULL ) == 0 )
  173. {
  174. fmerr = GetLastError();
  175. }
  176. else
  177. {
  178. }
  179. IF_DEBUG( COMMANDS )
  180. {
  181. if( fmerr == NO_ERROR )
  182. {
  183. DBGPRINTF(( DBG_CONTEXT,
  184. "mapped error %lu to %s\n",
  185. err,
  186. pszText ));
  187. }
  188. else
  189. {
  190. DBGPRINTF(( DBG_CONTEXT,
  191. "cannot map error %lu to text, error %lu\n",
  192. err,
  193. fmerr ));
  194. }
  195. }
  196. return pszText;
  197. } // AllocErrorText
  198. /*******************************************************************
  199. NAME: FreeErrorText
  200. SYNOPSIS: Frees the pointer returned by AllocErrorText.
  201. ENTRY: pszText - The text to free. Must be a pointer
  202. returned by AllocErrorText.
  203. HISTORY:
  204. KeithMo 27-Apr-1993 Created.
  205. ********************************************************************/
  206. VOID
  207. FreeErrorText(
  208. CHAR * pszText
  209. )
  210. {
  211. LocalFree( (HLOCAL)pszText );
  212. } // FreeErrorText
  213. DWORD
  214. OpenPathForAccess(
  215. LPHANDLE phFile,
  216. LPSTR pszPath,
  217. ULONG DesiredAccess,
  218. ULONG ShareAccess,
  219. HANDLE hImpersonation
  220. )
  221. /*++
  222. This function opens a path for access to do some verification
  223. or holding on to the file/directory when a user is logged on.
  224. Arguments:
  225. phFile - pointer to handle, where a handle is stored on
  226. successful return.
  227. pszPath - pointer to null terminated string containing the path
  228. for path to be opened.
  229. DesiredAccess - Access type to the file.
  230. ShareAccess - access flags for shared opens.
  231. hImpersonation - Impersonation token for this user - used for
  232. long filename check
  233. Returns:
  234. Win32 error code - NO_ERROR on success
  235. Author:
  236. MuraliK 14-Nov-1995
  237. --*/
  238. {
  239. WCHAR awchPath[MAX_PATH+8+1];
  240. DWORD dwError = NO_ERROR;
  241. if ( phFile == NULL) {
  242. return ( ERROR_INVALID_PARAMETER);
  243. }
  244. if (!TsMakeWidePath( pszPath, awchPath, MAX_PATH+8+1)) {
  245. return GetLastError();
  246. }
  247. *phFile = CreateFileW( awchPath, // path for the file
  248. DesiredAccess, // fdwAccess
  249. ShareAccess, // fdwShareMode
  250. NULL, // Security attributes
  251. OPEN_EXISTING, // fdwCreate
  252. FILE_FLAG_BACKUP_SEMANTICS, // fdwAttrsAndFlags
  253. NULL ); // hTemplateFile
  254. if ( *phFile == INVALID_HANDLE_VALUE) {
  255. dwError = GetLastError();
  256. }
  257. else {
  258. if ( strchr( pszPath, '~' )) {
  259. BOOL fShort;
  260. RevertToSelf();
  261. dwError = CheckIfShortFileName( (UCHAR *) pszPath,
  262. hImpersonation,
  263. &fShort );
  264. if ( !dwError && fShort )
  265. {
  266. dwError = ERROR_FILE_NOT_FOUND;
  267. DBG_REQUIRE( CloseHandle( *phFile ));
  268. *phFile = INVALID_HANDLE_VALUE;
  269. }
  270. }
  271. }
  272. return ( dwError);
  273. } // OpenPathForAccess()
  274. /*******************************************************************
  275. NAME: FlipSlashes
  276. SYNOPSIS: Flips the DOS-ish backslashes ('\') into Unix-ish
  277. forward slashes ('/').
  278. ENTRY: pszPath - The path to munge.
  279. fDirection - direction of destination. FLIP_SLASHES_TO_UNIX (0) or
  280. FLIP_SLASHES_TO_DOS (1)
  281. RETURNS: CHAR * - pszPath.
  282. HISTORY:
  283. KeithMo 04-Jun-1993 Created.
  284. ********************************************************************/
  285. CHAR *
  286. FlipSlashes(
  287. CHAR * pszPath,
  288. BOOL fDirection
  289. )
  290. {
  291. CHAR ch, chSrc, chDst;
  292. CHAR * pszScan = pszPath;
  293. if (fDirection == FLIP_SLASHES_TO_UNIX) {
  294. chSrc = '\\';
  295. chDst = '/';
  296. } else {
  297. chSrc = '/';
  298. chDst = '\\';
  299. }
  300. while( ( ch = *pszScan ) != '\0' )
  301. {
  302. //
  303. // skip DBCS character
  304. //
  305. if ( IsDBCSLeadByte( ch ) && *(pszScan+1) )
  306. {
  307. pszScan++;
  308. }
  309. else
  310. if( ch == chSrc )
  311. {
  312. *pszScan = chDst;
  313. }
  314. pszScan++;
  315. }
  316. return pszPath;
  317. } // FlipSlashes
  318. /*******************************************************************
  319. NAME:
  320. SYNOPSIS: breaks a username into it's domain and account components.
  321. usernames must be of the form:
  322. domain\user
  323. ENTRY: pszDomainAndUser - input string to parse
  324. ppszUser - on exit will point to user part
  325. ppszDomain - on exit will point to domain part
  326. pszLocalHostName - points to local host name to compare to domain
  327. pfIsLocalHost - flag returned to indicate the domain is local host
  328. RETURNS: TRUE if parsed correctly, FALSE otherwise.
  329. SIDEEFFECT: modifies the input by adding a \0 to separate domain from user
  330. HISTORY:
  331. RobSol 02-Apr-2001 Created.
  332. ********************************************************************/
  333. BOOL
  334. ParseUserName(
  335. IN PSTR pszDomainAndUser,
  336. IN OUT PSTR *ppszUser,
  337. IN OUT PSTR *ppszDomain,
  338. IN PCSTR pszLocalHostName,
  339. OUT BOOL *pfIsLocalHost
  340. )
  341. {
  342. *ppszUser = (PSTR)_mbschr( (PUCHAR)pszDomainAndUser, '\\' );
  343. *ppszDomain = pszDomainAndUser;
  344. if (*ppszUser == NULL) {
  345. return FALSE;
  346. } else {
  347. *(*ppszUser)++ = '\0';
  348. }
  349. if (**ppszUser == '\0' || **ppszDomain == '\0') {
  350. return FALSE;
  351. }
  352. *pfIsLocalHost = !_stricmp(*ppszDomain, pszLocalHostName);
  353. return TRUE;
  354. }