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.

480 lines
10 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. canon.c
  5. Abstract:
  6. Contains canonicalization routines for NetWare names.
  7. Author:
  8. Rita Wong (ritaw) 19-Feb-1993
  9. Environment:
  10. Revision History:
  11. --*/
  12. #include <procs.h>
  13. DWORD
  14. NwLibValidateLocalName(
  15. IN LPWSTR LocalName
  16. )
  17. /*++
  18. Routine Description:
  19. This routine checks to see if the supplied name is a valid
  20. DOS device name.
  21. Arguments:
  22. LocalName - Supplies a local device name. It can be any of
  23. the following:
  24. X:
  25. LPTn or LPTn:
  26. COMn or COMn:
  27. PRN or PRN:
  28. AUX or AUX:
  29. Return Value:
  30. NO_ERROR - LocalName is valid.
  31. WN_BAD_NETNAME - LocalName is invalid.
  32. --*/
  33. {
  34. DWORD LocalNameLength;
  35. //
  36. // Cannot be a NULL or empty string
  37. //
  38. if (LocalName == NULL || *LocalName == 0) {
  39. return WN_BAD_NETNAME;
  40. }
  41. LocalNameLength = wcslen(LocalName);
  42. if (LocalNameLength == 1) {
  43. return WN_BAD_NETNAME;
  44. }
  45. if (LocalName[LocalNameLength - 1] == L':') {
  46. if (! IS_VALID_TOKEN(LocalName, LocalNameLength - 1)) {
  47. return WN_BAD_NETNAME;
  48. }
  49. }
  50. else {
  51. if (! IS_VALID_TOKEN(LocalName, LocalNameLength)) {
  52. return WN_BAD_NETNAME;
  53. }
  54. }
  55. if (LocalNameLength == 2) {
  56. //
  57. // Must be in the form of X:
  58. //
  59. if (! iswalpha(*LocalName)) {
  60. return WN_BAD_NETNAME;
  61. }
  62. if (LocalName[1] != L':') {
  63. return WN_BAD_NETNAME;
  64. }
  65. return NO_ERROR;
  66. }
  67. if (RtlIsDosDeviceName_U(LocalName) == 0) {
  68. return WN_BAD_NETNAME;
  69. }
  70. //
  71. // Valid DOS device name but invalid redirection name
  72. //
  73. if (_wcsnicmp(LocalName, L"NUL", 3) == 0) {
  74. return WN_BAD_NETNAME;
  75. }
  76. return NO_ERROR;
  77. }
  78. DWORD
  79. NwLibCanonLocalName(
  80. IN LPWSTR LocalName,
  81. OUT LPWSTR *OutputBuffer,
  82. OUT LPDWORD OutputBufferLength OPTIONAL
  83. )
  84. /*++
  85. Routine Description:
  86. This routine canonicalizes the local name by uppercasing the string
  87. and converting the following:
  88. x: -> X:
  89. LPTn: -> LPTn
  90. COMn: -> COMn
  91. PRN or PRN: -> LPT1
  92. AUX or AUX: -> COM1
  93. Arguments:
  94. LocalName - Supplies a local device name.
  95. OutputBuffer - Receives a pointer to the canonicalized LocalName.
  96. OutputBufferLength - Receives the length of the canonicalized name
  97. in number of characters, if specified.
  98. Return Value:
  99. NO_ERROR - Successfully canonicalized the local name.
  100. WN_BAD_NETNAME - LocalName is invalid.
  101. ERROR_NOT_ENOUGH_MEMORY - Could not allocate output buffer.
  102. --*/
  103. {
  104. DWORD status;
  105. DWORD LocalNameLength;
  106. status = NwLibValidateLocalName(LocalName);
  107. if (status != NO_ERROR) {
  108. return status;
  109. }
  110. LocalNameLength = wcslen(LocalName);
  111. //
  112. // Allocate output buffer. Should be the size of the LocalName
  113. // plus 1 for the special case of PRN -> LPT1 or AUX -> COM1.
  114. //
  115. *OutputBuffer = (PVOID) LocalAlloc(
  116. LMEM_ZEROINIT,
  117. (LocalNameLength + 2) * sizeof(WCHAR)
  118. );
  119. if (*OutputBuffer == NULL) {
  120. KdPrint(("NWLIB: NwLibCanonLocalName LocalAlloc failed %lu\n",
  121. GetLastError()));
  122. return ERROR_NOT_ENOUGH_MEMORY;
  123. }
  124. wcscpy(*OutputBuffer, LocalName);
  125. if (LocalNameLength > 2) {
  126. if (_wcsnicmp(*OutputBuffer, L"PRN", 3) == 0) {
  127. //
  128. // Convert PRN or PRN: to LPT1
  129. //
  130. wcscpy(*OutputBuffer, L"LPT1");
  131. LocalNameLength = 4;
  132. }
  133. else if (_wcsnicmp(*OutputBuffer, L"AUX", 3) == 0) {
  134. //
  135. // Convert AUX or AUX: to COM1
  136. //
  137. wcscpy(*OutputBuffer, L"COM1");
  138. LocalNameLength = 4;
  139. }
  140. //
  141. // Remove trailing colon, if there is one, and decrement the length
  142. // of DOS device name.
  143. //
  144. if ((*OutputBuffer)[LocalNameLength - 1] == L':') {
  145. (*OutputBuffer)[--LocalNameLength] = 0;
  146. }
  147. }
  148. //
  149. // LocalName is always in uppercase.
  150. //
  151. _wcsupr(*OutputBuffer);
  152. if (ARGUMENT_PRESENT(OutputBufferLength)) {
  153. *OutputBufferLength = LocalNameLength;
  154. }
  155. return NO_ERROR;
  156. }
  157. DWORD
  158. NwLibCanonRemoteName(
  159. IN LPWSTR LocalName OPTIONAL,
  160. IN LPWSTR RemoteName,
  161. OUT LPWSTR *OutputBuffer,
  162. OUT LPDWORD OutputBufferLength OPTIONAL
  163. )
  164. /*++
  165. Routine Description:
  166. This routine validates and canonicalizes the supplied
  167. NetWare UNC name. It can be of any length in the form of:
  168. \\Server\Volume\Directory\Subdirectory
  169. Arguments:
  170. LocalName - Supplies the local device name. If it is NULL, then
  171. \\Server is an acceptable format for the UNC name.
  172. RemoteName - Supplies the UNC name.
  173. OutputBuffer - Receives a pointer to the canonicalized RemoteName.
  174. OutputBufferLength - Receives the length of the canonicalized name
  175. in number of characters, if specified.
  176. Return Value:
  177. NO_ERROR - RemoteName is valid.
  178. WN_BAD_NETNAME - RemoteName is invalid.
  179. --*/
  180. {
  181. DWORD RemoteNameLength;
  182. DWORD i;
  183. DWORD TokenLength;
  184. LPWSTR TokenPtr;
  185. BOOL fFirstToken = TRUE;
  186. //
  187. // Cannot be a NULL or empty string
  188. //
  189. if (RemoteName == NULL || *RemoteName == 0) {
  190. return WN_BAD_NETNAME;
  191. }
  192. RemoteNameLength = wcslen(RemoteName);
  193. //
  194. // Must be at least \\x\y if local device name is specified.
  195. // Otherwise it must be at least \\x.
  196. //
  197. if ((RemoteNameLength < 5 && ARGUMENT_PRESENT(LocalName)) ||
  198. (RemoteNameLength < 3)) {
  199. return WN_BAD_NETNAME;
  200. }
  201. //
  202. // First two characters must be "\\"
  203. //
  204. if (*RemoteName != L'\\' || RemoteName[1] != L'\\') {
  205. return WN_BAD_NETNAME;
  206. }
  207. if (! ARGUMENT_PRESENT(LocalName) &&
  208. (IS_VALID_TOKEN(&RemoteName[2], RemoteNameLength - 2))) {
  209. //
  210. // Return success for \\Server case.
  211. //
  212. *OutputBuffer = (PVOID) LocalAlloc(
  213. LMEM_ZEROINIT,
  214. (RemoteNameLength + 1) * sizeof(WCHAR)
  215. );
  216. if (*OutputBuffer == NULL) {
  217. KdPrint(("NWLIB: NwLibCanonRemoteName LocalAlloc failed %lu\n",
  218. GetLastError()));
  219. return ERROR_NOT_ENOUGH_MEMORY;
  220. }
  221. wcscpy(*OutputBuffer, RemoteName);
  222. return NO_ERROR;
  223. }
  224. //
  225. // Must have at least one more backslash after the third character
  226. //
  227. if (wcschr(&RemoteName[3], L'\\') == NULL) {
  228. return WN_BAD_NETNAME;
  229. }
  230. //
  231. // Last character cannot a backward slash
  232. //
  233. if (RemoteName[RemoteNameLength - 1] == L'\\') {
  234. return WN_BAD_NETNAME;
  235. }
  236. //
  237. // Allocate output buffer. Should be the size of the RemoteName
  238. // and space for an extra character to simplify parsing code below.
  239. //
  240. *OutputBuffer = (PVOID) LocalAlloc(
  241. LMEM_ZEROINIT,
  242. (RemoteNameLength + 2) * sizeof(WCHAR)
  243. );
  244. if (*OutputBuffer == NULL) {
  245. KdPrint(("NWLIB: NwLibCanonRemoteName LocalAlloc failed %lu\n",
  246. GetLastError()));
  247. return ERROR_NOT_ENOUGH_MEMORY;
  248. }
  249. wcscpy(*OutputBuffer, RemoteName);
  250. //
  251. // Convert all backslashes to NULL terminator, skipping first 2 chars.
  252. //
  253. for (i = 2; i < RemoteNameLength; i++) {
  254. if ((*OutputBuffer)[i] == L'\\') {
  255. (*OutputBuffer)[i] = 0;
  256. //
  257. // Two consecutive forward or backslashes is bad.
  258. //
  259. if ((i + 1 < RemoteNameLength) &&
  260. ((*OutputBuffer)[i + 1] == L'\\')) {
  261. (void) LocalFree((HLOCAL) *OutputBuffer);
  262. *OutputBuffer = NULL;
  263. return WN_BAD_NETNAME;
  264. }
  265. }
  266. }
  267. //
  268. // Validate each token of the RemoteName, separated by NULL terminator.
  269. //
  270. TokenPtr = *OutputBuffer + 2; // Skip first 2 chars
  271. while (*TokenPtr != 0) {
  272. TokenLength = wcslen(TokenPtr);
  273. if ( ( fFirstToken && !IS_VALID_SERVER_TOKEN(TokenPtr, TokenLength))
  274. || ( !fFirstToken && !IS_VALID_TOKEN(TokenPtr, TokenLength))
  275. )
  276. {
  277. (void) LocalFree((HLOCAL) *OutputBuffer);
  278. *OutputBuffer = NULL;
  279. return WN_BAD_NETNAME;
  280. }
  281. fFirstToken = FALSE;
  282. TokenPtr += TokenLength + 1;
  283. }
  284. //
  285. // Convert NULL separators to backslashes
  286. //
  287. for (i = 0; i < RemoteNameLength; i++) {
  288. if ((*OutputBuffer)[i] == 0) {
  289. (*OutputBuffer)[i] = L'\\';
  290. }
  291. }
  292. if (ARGUMENT_PRESENT(OutputBufferLength)) {
  293. *OutputBufferLength = RemoteNameLength;
  294. }
  295. return NO_ERROR;
  296. }
  297. DWORD
  298. NwLibCanonUserName(
  299. IN LPWSTR UserName,
  300. OUT LPWSTR *OutputBuffer,
  301. OUT LPDWORD OutputBufferLength OPTIONAL
  302. )
  303. /*++
  304. Routine Description:
  305. This routine canonicalizes the user name by checking to see
  306. if the name contains any illegal characters.
  307. Arguments:
  308. UserName - Supplies a username.
  309. OutputBuffer - Receives a pointer to the canonicalized UserName.
  310. OutputBufferLength - Receives the length of the canonicalized name
  311. in number of characters, if specified.
  312. Return Value:
  313. NO_ERROR - Successfully canonicalized the username.
  314. WN_BAD_NETNAME - UserName is invalid.
  315. ERROR_NOT_ENOUGH_MEMORY - Could not allocate output buffer.
  316. --*/
  317. {
  318. DWORD UserNameLength;
  319. //
  320. // Cannot be a NULL or empty string
  321. //
  322. if (UserName == NULL) {
  323. return WN_BAD_NETNAME;
  324. }
  325. UserNameLength = wcslen(UserName);
  326. if (! IS_VALID_TOKEN(UserName, UserNameLength)) {
  327. return WN_BAD_NETNAME;
  328. }
  329. //
  330. // Allocate output buffer. Should be the size of the UserName
  331. // plus 1 for the special case of PRN -> LPT1 or AUX -> COM1.
  332. //
  333. *OutputBuffer = (PVOID) LocalAlloc(
  334. LMEM_ZEROINIT,
  335. (UserNameLength + 1) * sizeof(WCHAR)
  336. );
  337. if (*OutputBuffer == NULL) {
  338. KdPrint(("NWLIB: NwLibCanonUserName LocalAlloc failed %lu\n",
  339. GetLastError()));
  340. return ERROR_NOT_ENOUGH_MEMORY;
  341. }
  342. wcscpy(*OutputBuffer, UserName);
  343. if (ARGUMENT_PRESENT(OutputBufferLength)) {
  344. *OutputBufferLength = UserNameLength;
  345. }
  346. return NO_ERROR;
  347. }