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.

496 lines
18 KiB

  1. /*++ BUILD Version: 0009 // Increment this if a change has global effects
  2. Copyright (c) 1987-1993 Microsoft Corporation
  3. Module Name:
  4. smbutils.c
  5. Abstract:
  6. This module implements the routines that aid in the assembly/disassembly of SMB's
  7. Author:
  8. Balan Sethu Raman (SethuR) 06-Mar-95 Created
  9. --*/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. #define BASE_DOS_ERROR ((NTSTATUS )0xC0010000L)
  13. #include "lmerr.h"
  14. #include "nb30.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE, SmbPutString)
  17. #pragma alloc_text(PAGE, SmbPutUnicodeString)
  18. #pragma alloc_text(PAGE, SmbPutUnicodeStringAndUpcase)
  19. #pragma alloc_text(PAGE, SmbPutUnicodeStringAsOemString)
  20. #pragma alloc_text(PAGE, SmbPutUnicodeStringAsOemStringAndUpcase)
  21. #endif
  22. NTSTATUS
  23. SmbPutString(
  24. PBYTE *pBufferPointer,
  25. PSTRING pString,
  26. PULONG pSize)
  27. {
  28. NTSTATUS Status;
  29. PBYTE pBuffer = *pBufferPointer;
  30. PAGED_CODE();
  31. if (*pSize > pString->Length) {
  32. RtlCopyMemory(
  33. pBuffer,
  34. pString->Buffer,
  35. pString->Length);
  36. *pSize -= pString->Length;
  37. *pBufferPointer = pBuffer + pString->Length;
  38. Status = STATUS_SUCCESS;
  39. } else {
  40. Status = STATUS_BUFFER_OVERFLOW;
  41. }
  42. return Status;
  43. }
  44. NTSTATUS
  45. SmbPutUnicodeString(
  46. PBYTE *pBufferPointer,
  47. PUNICODE_STRING pUnicodeString,
  48. PULONG pSize)
  49. {
  50. NTSTATUS Status;
  51. PBYTE pBuffer = *pBufferPointer;
  52. PAGED_CODE();
  53. if (*pSize >= (pUnicodeString->Length + sizeof(WCHAR))) {
  54. WCHAR NullChar = L'\0';
  55. RtlCopyMemory(
  56. pBuffer,
  57. pUnicodeString->Buffer,
  58. pUnicodeString->Length);
  59. RtlCopyMemory(
  60. (pBuffer + pUnicodeString->Length),
  61. &NullChar,
  62. sizeof(WCHAR));
  63. *pSize -= (pUnicodeString->Length + sizeof(WCHAR));
  64. *pBufferPointer = pBuffer + (pUnicodeString->Length + sizeof(WCHAR));
  65. Status = STATUS_SUCCESS;
  66. } else {
  67. Status = STATUS_BUFFER_OVERFLOW;
  68. }
  69. return Status;
  70. }
  71. NTSTATUS
  72. SmbPutUnicodeStringAndUpcase(
  73. PBYTE *pBufferPointer,
  74. PUNICODE_STRING pUnicodeString,
  75. PULONG pSize)
  76. {
  77. NTSTATUS Status;
  78. PBYTE pBuffer = *pBufferPointer;
  79. PAGED_CODE();
  80. if (*pSize >= (pUnicodeString->Length + sizeof(WCHAR))) {
  81. UNICODE_STRING BufferAsUnicode;
  82. WCHAR NullChar = L'\0';
  83. BufferAsUnicode.Buffer = (PWCHAR)pBuffer;
  84. BufferAsUnicode.Length = pUnicodeString->Length;
  85. BufferAsUnicode.MaximumLength = BufferAsUnicode.Length;
  86. RtlUpcaseUnicodeString(
  87. &BufferAsUnicode,
  88. pUnicodeString,
  89. FALSE);
  90. RtlCopyMemory(
  91. (pBuffer + pUnicodeString->Length),
  92. &NullChar,
  93. sizeof(WCHAR));
  94. *pSize -= (pUnicodeString->Length + sizeof(WCHAR));
  95. *pBufferPointer = pBuffer + (pUnicodeString->Length + sizeof(WCHAR));
  96. Status = STATUS_SUCCESS;
  97. } else {
  98. Status = STATUS_BUFFER_OVERFLOW;
  99. }
  100. return Status;
  101. }
  102. NTSTATUS
  103. SmbPutUnicodeStringAsOemString(
  104. PBYTE *pBufferPointer,
  105. PUNICODE_STRING pUnicodeString,
  106. PULONG pSize)
  107. {
  108. NTSTATUS Status;
  109. OEM_STRING OemString;
  110. PBYTE pBuffer = *pBufferPointer;
  111. PAGED_CODE();
  112. OemString.MaximumLength = (USHORT)*pSize;
  113. OemString.Buffer = pBuffer;
  114. // The Rtl routine pads the converted string with a NULL.
  115. Status = RtlUnicodeStringToOemString(
  116. &OemString, // destination string
  117. pUnicodeString, // source string
  118. FALSE); // No memory allocation for destination
  119. if (NT_SUCCESS(Status)) {
  120. if (OemString.Length < *pSize) {
  121. // put the null
  122. pBuffer += (OemString.Length + 1);
  123. *pBufferPointer = pBuffer;
  124. *pSize -= (OemString.Length + 1); // the NULL is not included in the length by the RTL routine.
  125. } else {
  126. Status = RX_MAP_STATUS(BUFFER_OVERFLOW);
  127. }
  128. }
  129. return Status;
  130. }
  131. NTSTATUS
  132. SmbPutUnicodeStringAsOemStringAndUpcase(
  133. PBYTE *pBufferPointer,
  134. PUNICODE_STRING pUnicodeString,
  135. PULONG pSize)
  136. {
  137. NTSTATUS Status;
  138. OEM_STRING OemString;
  139. PBYTE pBuffer = *pBufferPointer;
  140. PAGED_CODE();
  141. OemString.MaximumLength = (USHORT)*pSize;
  142. OemString.Buffer = pBuffer;
  143. // The Rtl routine pads the converted string with a NULL.
  144. Status = RtlUpcaseUnicodeStringToOemString(
  145. &OemString, // destination string
  146. pUnicodeString, // source string
  147. FALSE); // No memory allocation for destination
  148. if (NT_SUCCESS(Status)) {
  149. if (OemString.Length < *pSize) {
  150. // put the null
  151. pBuffer += (OemString.Length + 1);
  152. *pBufferPointer = pBuffer;
  153. *pSize -= (OemString.Length + 1); // the NULL is not included in the length by the RTL routine.
  154. } else {
  155. Status = STATUS_BUFFER_OVERFLOW;
  156. }
  157. }
  158. return Status;
  159. }
  160. //
  161. // The maps for mapping various error codes into NTSTATUSs
  162. //
  163. typedef struct _STATUS_MAP {
  164. USHORT ErrorCode;
  165. NTSTATUS ResultingStatus;
  166. } STATUS_MAP, *PSTATUS_MAP;
  167. STATUS_MAP
  168. SmbErrorMap[] = {
  169. { SMB_ERR_BAD_PASSWORD, STATUS_WRONG_PASSWORD },
  170. { SMB_ERR_ACCESS, STATUS_NETWORK_ACCESS_DENIED },
  171. { SMB_ERR_BAD_TID, STATUS_NETWORK_NAME_DELETED },
  172. { SMB_ERR_BAD_NET_NAME, STATUS_BAD_NETWORK_NAME }, // Invalid network name
  173. { SMB_ERR_BAD_DEVICE, STATUS_BAD_DEVICE_TYPE }, // Invalid device request
  174. { SMB_ERR_QUEUE_FULL, STATUS_PRINT_QUEUE_FULL }, // Print queue full
  175. { SMB_ERR_QUEUE_TOO_BIG, STATUS_NO_SPOOL_SPACE }, // No space on print dev
  176. { SMB_ERR_BAD_PRINT_FID, STATUS_PRINT_CANCELLED }, // Invalid printfile FID
  177. { SMB_ERR_SERVER_PAUSED, STATUS_SHARING_PAUSED }, // Server is paused
  178. { SMB_ERR_MESSAGE_OFF, STATUS_REQUEST_NOT_ACCEPTED }, // Server not receiving msgs
  179. { SMB_ERR_BAD_TYPE, STATUS_BAD_DEVICE_TYPE }, // Reserved
  180. { SMB_ERR_BAD_SMB_COMMAND, STATUS_NOT_IMPLEMENTED }, // SMB command not recognized
  181. { SMB_ERR_BAD_PERMITS, STATUS_NETWORK_ACCESS_DENIED }, // Access permissions invalid
  182. { SMB_ERR_NO_ROOM, STATUS_DISK_FULL }, // No room for buffer message
  183. { SMB_ERR_NO_RESOURCE, STATUS_REQUEST_NOT_ACCEPTED }, // No resources available for request
  184. { SMB_ERR_TOO_MANY_UIDS, STATUS_TOO_MANY_SESSIONS }, // Too many UIDs active in session
  185. { SMB_ERR_BAD_UID, STATUS_USER_SESSION_DELETED }, // UID not known as a valid UID
  186. { SMB_ERR_USE_MPX, STATUS_SMB_USE_MPX }, // Can't support Raw; use MPX
  187. { SMB_ERR_USE_STANDARD, STATUS_SMB_USE_STANDARD }, // Can't support Raw, use standard r/w
  188. { SMB_ERR_INVALID_NAME, STATUS_OBJECT_NAME_INVALID },
  189. { SMB_ERR_INVALID_NAME_RANGE, STATUS_OBJECT_NAME_INVALID },
  190. { SMB_ERR_NO_SUPPORT,STATUS_NOT_SUPPORTED }, // Function not supported
  191. { NERR_PasswordExpired, STATUS_PASSWORD_EXPIRED },
  192. { NERR_AccountExpired, STATUS_ACCOUNT_DISABLED },
  193. { NERR_InvalidLogonHours, STATUS_INVALID_LOGON_HOURS },
  194. { NERR_InvalidWorkstation, STATUS_INVALID_WORKSTATION },
  195. { NERR_DuplicateShare, STATUS_LOGON_FAILURE }
  196. // { SMB_ERR_QUEUE_EOF, STATUS_UNEXPECTED_NETWORK_ERROR },// EOF on print queue dump
  197. // { SMB_ERR_SERVER_ERROR, STATUS_UNEXPECTED_NETWORK_ERROR}, // Internal server error
  198. // { SMB_ERR_FILE_SPECS, STATUS_UNEXPECTED_NETWORK_ERROR }, // FID and pathname were incompatible
  199. // { SMB_ERR_BAD_ATTRIBUTE_MODE, STATUS_UNEXPECTED_NETWORK_ERROR }, // Invalid attribute mode specified
  200. // { SMB_ERR_NO_SUPPORT_INTERNAL,STATUS_UNEXPECTED_NETWORK_ERROR }, // Internal code for NO_SUPPORT--
  201. // // allows codes to be stored in a byte
  202. // { SMB_ERR_ERROR, STATUS_UNEXPECTED_NETWORK_ERROR },
  203. // { SMB_ERR_CONTINUE_MPX, STATUS_UNEXPECTED_NETWORK_ERROR }, // Reserved
  204. // { SMB_ERR_TOO_MANY_NAMES, STATUS_UNEXPECTED_NETWORK_ERROR }, // Too many remote user names
  205. // { SMB_ERR_TIMEOUT, STATUS_UNEXPECTED_NETWORK_ERROR }, // Operation was timed out
  206. // { SMB_ERR_RESERVED2, STATUS_UNEXPECTED_NETWORK_ERROR },
  207. // { SMB_ERR_RESERVED3, STATUS_UNEXPECTED_NETWORK_ERROR },
  208. // { SMB_ERR_RESERVED4, STATUS_UNEXPECTED_NETWORK_ERROR },
  209. // { SMB_ERR_RESERVED5, STATUS_UNEXPECTED_NETWORK_ERROR },
  210. };
  211. ULONG
  212. SmbErrorMapLength = sizeof(SmbErrorMap) / sizeof(SmbErrorMap[0]);
  213. STATUS_MAP
  214. Os2ErrorMap[] = {
  215. { ERROR_INVALID_FUNCTION, STATUS_NOT_IMPLEMENTED },
  216. { ERROR_FILE_NOT_FOUND, STATUS_NO_SUCH_FILE },
  217. { ERROR_PATH_NOT_FOUND, STATUS_OBJECT_PATH_NOT_FOUND },
  218. { ERROR_TOO_MANY_OPEN_FILES,STATUS_TOO_MANY_OPENED_FILES },
  219. { ERROR_ACCESS_DENIED, STATUS_ACCESS_DENIED },
  220. { ERROR_INVALID_HANDLE, STATUS_INVALID_HANDLE },
  221. { ERROR_NOT_ENOUGH_MEMORY, STATUS_INSUFFICIENT_RESOURCES },
  222. { ERROR_INVALID_ACCESS, STATUS_ACCESS_DENIED },
  223. { ERROR_INVALID_DATA, STATUS_DATA_ERROR },
  224. { ERROR_CURRENT_DIRECTORY, STATUS_DIRECTORY_NOT_EMPTY },
  225. { ERROR_NOT_SAME_DEVICE, STATUS_NOT_SAME_DEVICE },
  226. { ERROR_NO_MORE_FILES, STATUS_NO_MORE_FILES },
  227. { ERROR_WRITE_PROTECT, STATUS_MEDIA_WRITE_PROTECTED},
  228. { ERROR_NOT_READY, STATUS_DEVICE_NOT_READY },
  229. { ERROR_CRC, STATUS_CRC_ERROR },
  230. { ERROR_BAD_LENGTH, STATUS_DATA_ERROR },
  231. { ERROR_NOT_DOS_DISK, STATUS_DISK_CORRUPT_ERROR }, //***
  232. { ERROR_SECTOR_NOT_FOUND, STATUS_NONEXISTENT_SECTOR },
  233. { ERROR_OUT_OF_PAPER, STATUS_DEVICE_PAPER_EMPTY},
  234. { ERROR_SHARING_VIOLATION, STATUS_SHARING_VIOLATION },
  235. { ERROR_LOCK_VIOLATION, STATUS_FILE_LOCK_CONFLICT },
  236. { ERROR_WRONG_DISK, STATUS_WRONG_VOLUME },
  237. { ERROR_NOT_SUPPORTED, STATUS_NOT_SUPPORTED },
  238. { ERROR_REM_NOT_LIST, STATUS_REMOTE_NOT_LISTENING },
  239. { ERROR_DUP_NAME, STATUS_DUPLICATE_NAME },
  240. { ERROR_BAD_NETPATH, STATUS_BAD_NETWORK_PATH },
  241. { ERROR_NETWORK_BUSY, STATUS_NETWORK_BUSY },
  242. { ERROR_DEV_NOT_EXIST, STATUS_DEVICE_DOES_NOT_EXIST },
  243. { ERROR_TOO_MANY_CMDS, STATUS_TOO_MANY_COMMANDS },
  244. { ERROR_ADAP_HDW_ERR, STATUS_ADAPTER_HARDWARE_ERROR },
  245. { ERROR_BAD_NET_RESP, STATUS_INVALID_NETWORK_RESPONSE },
  246. { ERROR_UNEXP_NET_ERR, STATUS_UNEXPECTED_NETWORK_ERROR },
  247. { ERROR_BAD_REM_ADAP, STATUS_BAD_REMOTE_ADAPTER },
  248. { ERROR_PRINTQ_FULL, STATUS_PRINT_QUEUE_FULL },
  249. { ERROR_NO_SPOOL_SPACE, STATUS_NO_SPOOL_SPACE },
  250. { ERROR_PRINT_CANCELLED, STATUS_PRINT_CANCELLED },
  251. { ERROR_NETNAME_DELETED, STATUS_NETWORK_NAME_DELETED },
  252. { ERROR_NETWORK_ACCESS_DENIED, STATUS_NETWORK_ACCESS_DENIED },
  253. { ERROR_BAD_DEV_TYPE, STATUS_BAD_DEVICE_TYPE },
  254. { ERROR_BAD_NET_NAME, STATUS_BAD_NETWORK_NAME },
  255. { ERROR_TOO_MANY_NAMES, STATUS_TOO_MANY_NAMES },
  256. { ERROR_TOO_MANY_SESS, STATUS_TOO_MANY_SESSIONS },
  257. { ERROR_SHARING_PAUSED, STATUS_SHARING_PAUSED },
  258. { ERROR_REQ_NOT_ACCEP, STATUS_REQUEST_NOT_ACCEPTED },
  259. { ERROR_REDIR_PAUSED, STATUS_REDIRECTOR_PAUSED },
  260. { ERROR_FILE_EXISTS, STATUS_OBJECT_NAME_COLLISION },
  261. { ERROR_INVALID_PASSWORD, STATUS_WRONG_PASSWORD },
  262. { ERROR_INVALID_PARAMETER, STATUS_INVALID_PARAMETER },
  263. { ERROR_NET_WRITE_FAULT, STATUS_NET_WRITE_FAULT },
  264. { ERROR_BROKEN_PIPE, STATUS_PIPE_BROKEN },
  265. { ERROR_OPEN_FAILED, STATUS_OPEN_FAILED },
  266. { ERROR_BUFFER_OVERFLOW, STATUS_BUFFER_OVERFLOW },
  267. { ERROR_DISK_FULL, STATUS_DISK_FULL },
  268. { ERROR_SEM_TIMEOUT, STATUS_IO_TIMEOUT },
  269. { ERROR_INSUFFICIENT_BUFFER,STATUS_BUFFER_TOO_SMALL },
  270. { ERROR_INVALID_NAME, STATUS_OBJECT_NAME_INVALID },
  271. { ERROR_INVALID_LEVEL, STATUS_INVALID_LEVEL },
  272. { ERROR_BAD_PATHNAME, STATUS_OBJECT_PATH_INVALID }, //*
  273. { ERROR_BAD_PIPE, STATUS_INVALID_PARAMETER },
  274. { ERROR_PIPE_BUSY, STATUS_PIPE_NOT_AVAILABLE },
  275. { ERROR_NO_DATA, STATUS_PIPE_EMPTY },
  276. { ERROR_PIPE_NOT_CONNECTED, STATUS_PIPE_DISCONNECTED },
  277. { ERROR_MORE_DATA, STATUS_BUFFER_OVERFLOW },
  278. { ERROR_VC_DISCONNECTED, STATUS_VIRTUAL_CIRCUIT_CLOSED },
  279. { ERROR_INVALID_EA_NAME, STATUS_INVALID_EA_NAME },
  280. { ERROR_EA_LIST_INCONSISTENT,STATUS_EA_LIST_INCONSISTENT },
  281. // { ERROR_EA_LIST_TOO_LONG, STATUS_EA_LIST_TO_LONG },
  282. { ERROR_EAS_DIDNT_FIT, STATUS_EA_TOO_LARGE },
  283. { ERROR_EA_FILE_CORRUPT, STATUS_EA_CORRUPT_ERROR },
  284. { ERROR_EA_TABLE_FULL, STATUS_EA_CORRUPT_ERROR },
  285. { ERROR_INVALID_EA_HANDLE, STATUS_EA_CORRUPT_ERROR }
  286. // { ERROR_BAD_UNIT, STATUS_UNSUCCESSFUL}, // ***
  287. // { ERROR_BAD_COMMAND, STATUS_UNSUCCESSFUL}, // ***
  288. // { ERROR_SEEK, STATUS_UNSUCCESSFUL },// ***
  289. // { ERROR_WRITE_FAULT, STATUS_UNSUCCESSFUL}, // ***
  290. // { ERROR_READ_FAULT, STATUS_UNSUCCESSFUL}, // ***
  291. // { ERROR_GEN_FAILURE, STATUS_UNSUCCESSFUL }, // ***
  292. };
  293. ULONG
  294. Os2ErrorMapLength = sizeof(Os2ErrorMap) / sizeof(Os2ErrorMap[0]);
  295. NTSTATUS
  296. GetSmbResponseNtStatus(
  297. PSMB_HEADER pSmbHeader,
  298. PSMB_EXCHANGE pExchange
  299. )
  300. {
  301. NTSTATUS Status;
  302. USHORT Error;
  303. USHORT i;
  304. ASSERT( pSmbHeader != NULL );
  305. // If this SMB contains an NT status for the operation, return
  306. // that, otherwise map the resulting error.
  307. if (SmbGetUshort(&pSmbHeader->Flags2) & SMB_FLAGS2_NT_STATUS) {
  308. Status = SmbGetUlong( & ((PNT_SMB_HEADER)pSmbHeader)->Status.NtStatus );
  309. if ((Status == STATUS_SUCCESS) || NT_ERROR(Status) || NT_WARNING(Status)) {
  310. if (Status == STATUS_RETRY) {
  311. Status = STATUS_UNEXPECTED_NETWORK_ERROR;
  312. }
  313. return Status;
  314. }
  315. // else fall through and treat it as an SMB error ..
  316. // This needs to be done because in certain cases NT servers return SMB
  317. // specific error codes eventhough the NTSTATUS flag is set
  318. }
  319. if (pSmbHeader->ErrorClass == SMB_ERR_SUCCESS) {
  320. return STATUS_SUCCESS;
  321. }
  322. Error = SmbGetUshort(&pSmbHeader->Error);
  323. if (Error == SMB_ERR_SUCCESS) {
  324. // Umm, non success ErrorClass but success Error code.
  325. Status = STATUS_UNEXPECTED_NETWORK_ERROR;
  326. } else {
  327. // Map the error code depending on Error Class
  328. switch (pSmbHeader->ErrorClass) {
  329. case SMB_ERR_CLASS_DOS:
  330. case SMB_ERR_CLASS_HARDWARE:
  331. Status = BASE_DOS_ERROR + Error;
  332. for (i = 0; i < Os2ErrorMapLength; i++) {
  333. if (Os2ErrorMap[i].ErrorCode == Error) {
  334. Status = Os2ErrorMap[i].ResultingStatus;
  335. break;
  336. }
  337. }
  338. break;
  339. case SMB_ERR_CLASS_SERVER:
  340. Status = STATUS_UNEXPECTED_NETWORK_ERROR;
  341. for (i = 0; i < SmbErrorMapLength; i++) {
  342. if (SmbErrorMap[i].ErrorCode == Error) {
  343. //The error of STATUS_NETWORK_ACCESS_DENIED should be mapped as STATUS_NO_SUCH_FILE for
  344. //the non-NT servers in case it tries to access the PIPE.
  345. if (SmbErrorMap[i].ResultingStatus == STATUS_NETWORK_ACCESS_DENIED) {
  346. SMBCE_SERVER Server = pExchange->SmbCeContext.pServerEntry->Server;
  347. NET_ROOT_TYPE NetRootType = pExchange->SmbCeContext.pVNetRoot->pNetRoot->Type;
  348. if (NetRootType == NET_ROOT_PIPE) {
  349. if ( (Server.Dialect != NTLANMAN_DIALECT) ||
  350. !FlagOn(Server.DialectFlags,DF_NT_STATUS) ) {
  351. Status = STATUS_NO_SUCH_FILE;
  352. break;
  353. }
  354. }
  355. }
  356. Status = SmbErrorMap[i].ResultingStatus;
  357. break;
  358. }
  359. }
  360. break;
  361. default:
  362. Status = STATUS_UNEXPECTED_NETWORK_ERROR;
  363. break;
  364. }
  365. }
  366. return Status;
  367. }
  368. BOOLEAN
  369. IsValidShortFileName(
  370. PUNICODE_STRING Name
  371. )
  372. {
  373. BOOLEAN IsValidName = TRUE;
  374. int NumberOfChars;
  375. int CurrentNameStart = 0;
  376. int CurrentNameEnd = 0;
  377. int CurrentDot = 0;
  378. int i;
  379. if (Name == NULL) {
  380. return TRUE;
  381. }
  382. NumberOfChars = Name->Length/sizeof(UNICODE_NULL);
  383. while(IsValidName && CurrentNameStart < NumberOfChars) {
  384. CurrentNameEnd = NumberOfChars;
  385. for (i=CurrentNameStart+1;i<NumberOfChars;i++) {
  386. if (Name->Buffer[i] == L'\\') {
  387. CurrentNameEnd = i;
  388. break;
  389. }
  390. }
  391. if (CurrentNameEnd - CurrentNameStart > 13) {
  392. IsValidName = FALSE;
  393. }
  394. if (IsValidName) {
  395. CurrentDot = CurrentNameEnd;
  396. for (i=CurrentNameStart;i<CurrentNameEnd;i++) {
  397. if (Name->Buffer[i] == L'.') {
  398. if (CurrentDot == CurrentNameEnd) {
  399. CurrentDot = i;
  400. } else {
  401. IsValidName = FALSE;
  402. }
  403. }
  404. }
  405. if (IsValidName) {
  406. if (CurrentDot - CurrentNameStart > 9 ||
  407. CurrentNameEnd - CurrentDot > 4) {
  408. IsValidName = FALSE;
  409. }
  410. }
  411. }
  412. CurrentNameStart = CurrentNameEnd;
  413. }
  414. return IsValidName;
  415. }
  416.