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.

358 lines
8.2 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1997-1999 Microsoft Corporation
  4. // All rights reserved.
  5. //
  6. // File Name:
  7. // chknames.c
  8. //
  9. // Description:
  10. // Code to check whether the given filename/netname/sharname etc...
  11. // contain illegal chars or not.
  12. //
  13. // These are used to validate such things as the TargetPath setting,
  14. // net printers and computername.
  15. //
  16. // Exports:
  17. // --------
  18. // IsValidComputerName
  19. // IsValidNetShareName
  20. // IsValidFileName8_3
  21. // IsValidPathNameNoRoot8_3ot.
  22. //
  23. //----------------------------------------------------------------------------
  24. #include "pch.h"
  25. //
  26. // The below list of illegal netnames characters was stolen from setup
  27. // source code during NT5 Beta3 timeframe (end of 1998).
  28. //
  29. LPTSTR IllegalNetNameChars = _T("\"/\\[]:|<>+=;,?*.");
  30. //
  31. // The below list of illegal filename characters were stolen from fileio
  32. // test sources at NT5 Beta3 timeframe.
  33. //
  34. // #define ILLEGAL_FAT_CHARS "\"*+,/:;<=>?[]|\\"
  35. // #define ILLEGAL_FATLONG_CHARS "\"*/:<>?|\\"
  36. // #define ILLEGAL_NETWARE_CHARS "\"*+,/:;<=>?[]|\\ "
  37. // #define ILLEGAL_HPFS_CHARS "\"*/:<>?|\\"
  38. // #define ILLEGAL_NTFS_CHARS "\"*/<>?|\\"
  39. //
  40. // In addition to the above list, strict 8.3 also includes:
  41. // 1. no spaces
  42. // 2. only 1 dot
  43. //
  44. LPTSTR IllegalFatChars = _T("\"*+,/:;<=>?[]|\\ ");
  45. //
  46. // Enum constants, one of these must be passed to IsNameValid
  47. //
  48. enum {
  49. NAME_NETNAME = 1,
  50. NAME_FILESYS_8DOT3
  51. };
  52. //---------------------------------------------------------------------------
  53. //
  54. // Function: IsNameValid
  55. //
  56. // Purpose: Internal support routine that checks whether the given name
  57. // contains invalid chars or not. The list of printable invalid
  58. // chars is given as an arg. Control characters are always
  59. // invalid.
  60. //
  61. //---------------------------------------------------------------------------
  62. static
  63. BOOL
  64. IsNameValid(
  65. LPTSTR NameToCheck,
  66. LPTSTR IllegalChars,
  67. int iNameType
  68. )
  69. {
  70. UINT Length;
  71. UINT u;
  72. UINT nDots = 0;
  73. Length = lstrlen(NameToCheck);
  74. //
  75. // Want at least one character.
  76. //
  77. if(!Length) {
  78. return(FALSE);
  79. }
  80. //
  81. // No Leading/trailing spaces if this is a network name
  82. //
  83. if ( iNameType == NAME_NETNAME ) {
  84. if((NameToCheck[0] == _T(' ')) || (NameToCheck[Length-1] == _T(' '))) {
  85. return(FALSE);
  86. }
  87. }
  88. //
  89. // Control chars are invalid, as are characters in the illegal chars list.
  90. //
  91. for(u=0; u<Length; u++) {
  92. if( NameToCheck[u] <= _T(' ') )
  93. {
  94. return( FALSE );
  95. }
  96. if( wcschr( IllegalFatChars,NameToCheck[u] ) )
  97. {
  98. return( FALSE );
  99. }
  100. if( NameToCheck[u] == _T('.') )
  101. {
  102. nDots++;
  103. }
  104. }
  105. //
  106. // For 8.3 names be sure there is only max of 1 dot in the name, and
  107. // check that each part has <=8 and <=3 chars respectively. Als, don't
  108. // allow a name like this: .foo.
  109. //
  110. if ( iNameType == NAME_FILESYS_8DOT3 ) {
  111. TCHAR *p;
  112. if ( nDots > 1 )
  113. return FALSE;
  114. if ( p = wcschr( NameToCheck, _T('.') ) ) {
  115. if ( p - NameToCheck > 8 || p - NameToCheck == 0 )
  116. return FALSE;
  117. if ( Length - (p - NameToCheck) - 1 > 3 )
  118. return FALSE;
  119. } else {
  120. if ( Length > 8 )
  121. return FALSE;
  122. }
  123. }
  124. //
  125. // We got here, name is ok.
  126. //
  127. return(TRUE);
  128. }
  129. //---------------------------------------------------------------------------
  130. //
  131. // Function: IsNetNameValid
  132. //
  133. // Purpose: Internal support routine to check for invalid chars in a
  134. // single piece of a network name. See IsValidComputerName and
  135. // IsValidNetShareName.
  136. //
  137. //---------------------------------------------------------------------------
  138. BOOL
  139. IsNetNameValid(
  140. LPTSTR NameToCheck
  141. )
  142. {
  143. return IsNameValid(NameToCheck, IllegalNetNameChars, NAME_NETNAME);
  144. }
  145. //---------------------------------------------------------------------------
  146. //
  147. // Function: IsValidComputerName
  148. //
  149. // Purpose: Checks whether the given computer name contains invalid chars.
  150. //
  151. //---------------------------------------------------------------------------
  152. BOOL
  153. IsValidComputerName(
  154. LPTSTR ComputerName
  155. )
  156. {
  157. return IsNetNameValid(ComputerName);
  158. }
  159. //---------------------------------------------------------------------------
  160. //
  161. // Function: IsValidNetShareName
  162. //
  163. // Purpose: Checks whether the given netshare name contains invalid
  164. // chars, and whether it is of valid format. Only \\srv\share
  165. // form is permitted.
  166. //
  167. //---------------------------------------------------------------------------
  168. BOOL
  169. IsValidNetShareName(
  170. LPTSTR NetShareName
  171. )
  172. {
  173. TCHAR *pEnd;
  174. //
  175. // Has to have \\ at the beginning
  176. //
  177. if ( NetShareName[0] != _T('\\') ||
  178. NetShareName[1] != _T('\\') )
  179. return FALSE;
  180. //
  181. // Isolate the 'srv' in \\srv\share and validate it for bogus chars
  182. //
  183. NetShareName += 2;
  184. if ( (pEnd = wcschr(NetShareName, _T('\\'))) == NULL )
  185. return FALSE;
  186. *pEnd = _T('\0');
  187. if ( ! IsNetNameValid(NetShareName) ) {
  188. *pEnd = _T('\\');
  189. return FALSE;
  190. }
  191. *pEnd = _T('\\');
  192. //
  193. // Validate the 'share' in \\srv\share
  194. //
  195. pEnd++;
  196. if ( ! IsNetNameValid(pEnd) )
  197. return FALSE;
  198. return( TRUE );
  199. }
  200. //---------------------------------------------------------------------------
  201. //
  202. // Function: IsValidFileName8_3
  203. //
  204. // Purpose: Checks whether the given filename, or single piece of a pathname
  205. // contains invalid chars or not, and whether it follows 8.3 naming
  206. // rules.
  207. //
  208. //---------------------------------------------------------------------------
  209. BOOL
  210. IsValidFileName8_3(
  211. LPTSTR FileName
  212. )
  213. {
  214. TCHAR *p;
  215. int nDots;
  216. //
  217. // Check for illegal chars, lead/trail whitespace is illegal for 8.3
  218. //
  219. if ( ! IsNameValid(FileName, IllegalFatChars, NAME_FILESYS_8DOT3) )
  220. return FALSE;
  221. //
  222. // Be sure there is zero or one dot
  223. //
  224. for ( p=FileName, nDots=0; *p; p++ ) {
  225. if ( *p == _T('.') )
  226. nDots++;
  227. }
  228. if ( nDots > 1 )
  229. return FALSE;
  230. return TRUE;
  231. }
  232. //---------------------------------------------------------------------------
  233. //
  234. // Function: IsValidPathNameNoRoot8_3
  235. //
  236. // Purpose: Checks whether the given pathname contains invalid chars or not.
  237. // A drive_letter: or \\unc\name are not permitted. The pathname
  238. // must also follow strict 8.3 rules. This is useful for
  239. // TargetPath setting (for e.g.)
  240. //
  241. //---------------------------------------------------------------------------
  242. BOOL
  243. IsValidPathNameNoRoot8_3(
  244. LPTSTR PathName
  245. )
  246. {
  247. TCHAR *p = PathName, *pEnd, Remember;
  248. //
  249. // No UNC names
  250. //
  251. if ( PathName[0] == _T('\\') && PathName[1] == _T('\\') )
  252. return FALSE;
  253. //
  254. // No drive letter allowed
  255. //
  256. if ( towupper(PathName[0]) >= _T('A') &&
  257. towupper(PathName[0]) <= _T('Z') &&
  258. PathName[1] == _T(':') ) {
  259. return FALSE;
  260. }
  261. //
  262. // Loop until the end of this string breaking out each piece of
  263. // the pathname and checking for bad chars.
  264. //
  265. // e.g. foo1\foo2\foo3, call IsValidFileName8_3() 3 times with the
  266. // little piece.
  267. //
  268. do {
  269. while ( *p && *p == _T('\\') )
  270. p++;
  271. for ( pEnd = p; *pEnd && *pEnd != _T('\\'); pEnd++ )
  272. ;
  273. Remember = *pEnd;
  274. *pEnd = _T('\0');
  275. if ( ! IsValidFileName8_3(p) ) {
  276. *pEnd = Remember;
  277. return FALSE;
  278. }
  279. *pEnd = Remember;
  280. p = pEnd;
  281. } while ( *p );
  282. //
  283. // Made it here, we're ok
  284. //
  285. return TRUE;
  286. }