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.

738 lines
19 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. Convert.c
  5. Abstract:
  6. This module implements conversion routine to map NT formats to
  7. Netware and vice versa.
  8. Author:
  9. Manny Weiser [MannyW] 3-Mar-1993
  10. Revision History:
  11. --*/
  12. #include "Procs.h"
  13. typedef union _NCP_DATE {
  14. USHORT Ushort;
  15. struct {
  16. USHORT Day : 5;
  17. USHORT Month : 4;
  18. USHORT Year : 7;
  19. } Struct;
  20. } NCP_DATE;
  21. typedef union _NCP_TIME {
  22. USHORT Ushort;
  23. struct {
  24. USHORT TwoSeconds : 5;
  25. USHORT Minutes : 6;
  26. USHORT Hours : 5;
  27. } Struct;
  28. } NCP_TIME;
  29. #define BASE_DOS_ERROR ((NTSTATUS )0xC0010000L)
  30. struct {
  31. UCHAR NetError;
  32. NTSTATUS ResultingStatus;
  33. } Error_Map[] = {
  34. // NetWare specific error mappings
  35. { 1, STATUS_DISK_FULL },
  36. {128, STATUS_SHARING_VIOLATION },
  37. {129, STATUS_INSUFF_SERVER_RESOURCES },
  38. {130, STATUS_ACCESS_DENIED },
  39. {131, STATUS_DATA_ERROR },
  40. {132, STATUS_ACCESS_DENIED },
  41. {133, STATUS_OBJECT_NAME_COLLISION },
  42. {134, STATUS_OBJECT_NAME_COLLISION },
  43. {135, STATUS_OBJECT_NAME_INVALID },
  44. {136, STATUS_INVALID_HANDLE },
  45. {137, STATUS_ACCESS_DENIED },
  46. {138, STATUS_ACCESS_DENIED },
  47. {139, STATUS_ACCESS_DENIED },
  48. {140, STATUS_ACCESS_DENIED },
  49. {141, STATUS_SHARING_VIOLATION },
  50. {142, STATUS_SHARING_VIOLATION },
  51. {143, STATUS_ACCESS_DENIED },
  52. {144, STATUS_ACCESS_DENIED },
  53. {145, STATUS_OBJECT_NAME_COLLISION },
  54. {146, STATUS_OBJECT_NAME_COLLISION },
  55. {147, STATUS_ACCESS_DENIED },
  56. {148, STATUS_ACCESS_DENIED },
  57. {149, STATUS_ACCESS_DENIED },
  58. {150, STATUS_INSUFF_SERVER_RESOURCES },
  59. {151, STATUS_NO_SPOOL_SPACE },
  60. {152, STATUS_NO_SUCH_DEVICE },
  61. {153, STATUS_DISK_FULL },
  62. {154, STATUS_NOT_SAME_DEVICE },
  63. {155, STATUS_INVALID_HANDLE },
  64. {156, STATUS_OBJECT_PATH_NOT_FOUND },
  65. {157, STATUS_INSUFF_SERVER_RESOURCES },
  66. {158, STATUS_OBJECT_PATH_INVALID },
  67. {159, STATUS_SHARING_VIOLATION },
  68. {160, STATUS_DIRECTORY_NOT_EMPTY },
  69. {161, STATUS_DATA_ERROR },
  70. {162, STATUS_FILE_LOCK_CONFLICT },
  71. {165, STATUS_OBJECT_NAME_NOT_FOUND },
  72. {191, STATUS_OBJECT_NAME_INVALID }, // Name space not loaded
  73. {192, STATUS_ACCESS_DENIED},
  74. {193, STATUS_ACCOUNT_RESTRICTION },
  75. {194, STATUS_ACCOUNT_RESTRICTION },
  76. {195, STATUS_ACCOUNT_DISABLED},
  77. {197, STATUS_ACCOUNT_DISABLED },
  78. {198, STATUS_ACCESS_DENIED },
  79. {211, STATUS_ACCESS_DENIED },
  80. {212, STATUS_PRINT_QUEUE_FULL },
  81. {213, STATUS_PRINT_CANCELLED },
  82. {214, STATUS_ACCESS_DENIED },
  83. {215, STATUS_PASSWORD_RESTRICTION },
  84. {216, STATUS_PASSWORD_RESTRICTION },
  85. #ifdef QFE_BUILD
  86. {217, STATUS_ACCOUNT_RESTRICTION },
  87. {218, STATUS_ACCOUNT_RESTRICTION },
  88. {219, STATUS_ACCOUNT_RESTRICTION },
  89. #else
  90. {217, STATUS_CONNECTION_COUNT_LIMIT },
  91. {218, STATUS_LOGIN_TIME_RESTRICTION },
  92. {219, STATUS_LOGIN_WKSTA_RESTRICTION },
  93. #endif
  94. {220, STATUS_ACCOUNT_DISABLED },
  95. {222, STATUS_PASSWORD_EXPIRED },
  96. {223, NWRDR_PASSWORD_HAS_EXPIRED },
  97. {231, STATUS_REMOTE_SESSION_LIMIT },
  98. {236, STATUS_UNEXPECTED_NETWORK_ERROR },
  99. {251, STATUS_INVALID_PARAMETER },
  100. {252, STATUS_NO_MORE_ENTRIES },
  101. {253, STATUS_FILE_LOCK_CONFLICT },
  102. {254, STATUS_FILE_LOCK_CONFLICT },
  103. {255, STATUS_UNSUCCESSFUL},
  104. // DOS error mappings
  105. //{ ERROR_INVALID_FUNCTION, STATUS_NOT_IMPLEMENTED },
  106. { ERROR_FILE_NOT_FOUND, STATUS_NO_SUCH_FILE },
  107. { ERROR_PATH_NOT_FOUND, STATUS_OBJECT_PATH_NOT_FOUND },
  108. { ERROR_TOO_MANY_OPEN_FILES, STATUS_TOO_MANY_OPENED_FILES },
  109. { ERROR_ACCESS_DENIED, STATUS_ACCESS_DENIED },
  110. { ERROR_INVALID_HANDLE, STATUS_INVALID_HANDLE },
  111. { ERROR_NOT_ENOUGH_MEMORY, STATUS_INSUFFICIENT_RESOURCES },
  112. { ERROR_INVALID_ACCESS, STATUS_ACCESS_DENIED },
  113. { ERROR_INVALID_DATA, STATUS_DATA_ERROR },
  114. { ERROR_CURRENT_DIRECTORY, STATUS_DIRECTORY_NOT_EMPTY },
  115. { ERROR_NOT_SAME_DEVICE, STATUS_NOT_SAME_DEVICE },
  116. { ERROR_NO_MORE_FILES, STATUS_NO_MORE_FILES },
  117. /* */
  118. /* These are the universal int 24 mappings for the old INT 24 set of errors */
  119. /* */
  120. { ERROR_WRITE_PROTECT, STATUS_MEDIA_WRITE_PROTECTED},
  121. { ERROR_BAD_UNIT, STATUS_UNSUCCESSFUL}, // ***
  122. { ERROR_NOT_READY, STATUS_DEVICE_NOT_READY },
  123. { ERROR_BAD_COMMAND, STATUS_UNSUCCESSFUL}, // ***
  124. { ERROR_CRC, STATUS_CRC_ERROR },
  125. { ERROR_BAD_LENGTH, STATUS_DATA_ERROR },
  126. { ERROR_SEEK, STATUS_UNSUCCESSFUL },// ***
  127. { ERROR_NOT_DOS_DISK, STATUS_DISK_CORRUPT_ERROR }, //***
  128. { ERROR_SECTOR_NOT_FOUND, STATUS_NONEXISTENT_SECTOR },
  129. { ERROR_OUT_OF_PAPER, STATUS_DEVICE_PAPER_EMPTY},
  130. { ERROR_WRITE_FAULT, STATUS_UNSUCCESSFUL}, // ***
  131. { ERROR_READ_FAULT, STATUS_UNSUCCESSFUL}, // ***
  132. { ERROR_GEN_FAILURE, STATUS_UNSUCCESSFUL }, // ***
  133. /* */
  134. /* These are the new 3.0 error codes reported through INT 24 */
  135. /* */
  136. { ERROR_SHARING_VIOLATION, STATUS_SHARING_VIOLATION },
  137. { ERROR_LOCK_VIOLATION, STATUS_FILE_LOCK_CONFLICT },
  138. { ERROR_WRONG_DISK, STATUS_WRONG_VOLUME },
  139. // { ERROR_FCB_UNAVAILABLE, },
  140. // { ERROR_SHARING_BUFFER_EXCEEDED, },
  141. /* */
  142. /* New OEM network-related errors are 50-79 */
  143. /* */
  144. { ERROR_NOT_SUPPORTED, STATUS_NOT_SUPPORTED },
  145. { ERROR_REM_NOT_LIST, STATUS_REMOTE_NOT_LISTENING },
  146. { ERROR_DUP_NAME, STATUS_DUPLICATE_NAME },
  147. { ERROR_BAD_NETPATH, STATUS_BAD_NETWORK_PATH },
  148. { ERROR_NETWORK_BUSY, STATUS_NETWORK_BUSY },
  149. { ERROR_DEV_NOT_EXIST, STATUS_DEVICE_DOES_NOT_EXIST },
  150. { ERROR_TOO_MANY_CMDS, STATUS_TOO_MANY_COMMANDS },
  151. { ERROR_ADAP_HDW_ERR, STATUS_ADAPTER_HARDWARE_ERROR },
  152. { ERROR_BAD_NET_RESP, STATUS_INVALID_NETWORK_RESPONSE },
  153. { ERROR_UNEXP_NET_ERR, STATUS_UNEXPECTED_NETWORK_ERROR },
  154. { ERROR_BAD_REM_ADAP, STATUS_BAD_REMOTE_ADAPTER },
  155. { ERROR_PRINTQ_FULL, STATUS_PRINT_QUEUE_FULL },
  156. { ERROR_NO_SPOOL_SPACE, STATUS_NO_SPOOL_SPACE },
  157. { ERROR_PRINT_CANCELLED, STATUS_PRINT_CANCELLED },
  158. { ERROR_NETNAME_DELETED, STATUS_NETWORK_NAME_DELETED },
  159. { ERROR_NETWORK_ACCESS_DENIED, STATUS_NETWORK_ACCESS_DENIED },
  160. { ERROR_BAD_DEV_TYPE, STATUS_BAD_DEVICE_TYPE },
  161. { ERROR_BAD_NET_NAME, STATUS_BAD_NETWORK_NAME },
  162. { ERROR_TOO_MANY_NAMES, STATUS_TOO_MANY_NAMES },
  163. { ERROR_TOO_MANY_SESS, STATUS_REMOTE_SESSION_LIMIT },
  164. { ERROR_SHARING_PAUSED, STATUS_SHARING_PAUSED },
  165. { ERROR_REQ_NOT_ACCEP, STATUS_REQUEST_NOT_ACCEPTED },
  166. { ERROR_REDIR_PAUSED, STATUS_REDIRECTOR_PAUSED },
  167. /* */
  168. /* End of INT 24 reportable errors */
  169. /* */
  170. { ERROR_FILE_EXISTS, STATUS_OBJECT_NAME_COLLISION },
  171. // { ERROR_DUP_FCB, },
  172. // { ERROR_CANNOT_MAKE, },
  173. // { ERROR_FAIL_I24, },
  174. /* */
  175. /* New 3.0 network related error codes */
  176. /* */
  177. // { ERROR_OUT_OF_STRUCTURES, },
  178. // { ERROR_ALREADY_ASSIGNED, },
  179. { ERROR_INVALID_PASSWORD, STATUS_WRONG_PASSWORD },
  180. { ERROR_INVALID_PARAMETER, STATUS_INVALID_PARAMETER },
  181. { ERROR_NET_WRITE_FAULT, STATUS_NET_WRITE_FAULT },
  182. /* */
  183. /* New error codes for 4.0 */
  184. /* */
  185. // { ERROR_NO_PROC_SLOTS, },
  186. // { ERROR_NOT_FROZEN, },
  187. // { ERR_TSTOVFL, },
  188. // { ERR_TSTDUP, },
  189. // { ERROR_NO_ITEMS, },
  190. // { ERROR_INTERRUPT, },
  191. // { ERROR_TOO_MANY_SEMAPHORES, },
  192. // { ERROR_EXCL_SEM_ALREADY_OWNED, },
  193. // { ERROR_SEM_IS_SET, },
  194. // { ERROR_TOO_MANY_SEM_REQUESTS, },
  195. // { ERROR_INVALID_AT_INTERRUPT_TIME, },
  196. // { ERROR_SEM_OWNER_DIED, },
  197. // { ERROR_SEM_USER_LIMIT, },
  198. // { ERROR_DISK_CHANGE, },
  199. // { ERROR_DRIVE_LOCKED, },
  200. { ERROR_BROKEN_PIPE, STATUS_PIPE_BROKEN },
  201. /* */
  202. /* New error codes for 5.0 */
  203. /* */
  204. //
  205. // NOTE: ERROR_OPEN_FAILED is handled specially.
  206. //
  207. //
  208. // The mapping of ERROR_OPEN_FAILED is context sensitive. If the
  209. // disposition requested in the Open_AndX SMB is FILE_CREATE, this
  210. // error means that the file already existed. If the disposition
  211. // is FILE_OPEN, it means that the file does NOT exist!
  212. //
  213. { ERROR_OPEN_FAILED, STATUS_OPEN_FAILED },
  214. // { ERROR_BUFFER_OVERFLOW, },
  215. { ERROR_DISK_FULL, STATUS_DISK_FULL },
  216. // { ERROR_NO_MORE_SEARCH_HANDLES, },
  217. // { ERROR_INVALID_TARGET_HANDLE, },
  218. // { ERROR_PROTECTION_VIOLATION, STATUS_ACCESS_VIOLATION },
  219. // { ERROR_VIOKBD_REQUEST, },
  220. // { ERROR_INVALID_CATEGORY, },
  221. // { ERROR_INVALID_VERIFY_SWITCH, },
  222. // { ERROR_BAD_DRIVER_LEVEL, },
  223. // { ERROR_CALL_NOT_IMPLEMENTED, },
  224. { ERROR_SEM_TIMEOUT, STATUS_IO_TIMEOUT },
  225. { ERROR_INSUFFICIENT_BUFFER, STATUS_BUFFER_TOO_SMALL },
  226. { ERROR_INVALID_NAME, STATUS_OBJECT_NAME_INVALID },
  227. { ERROR_INVALID_LEVEL, STATUS_INVALID_LEVEL },
  228. // { ERROR_NO_VOLUME_LABEL, },
  229. /* NOTE: DosQFSInfo no longer returns the above error; it is still here for */
  230. /* api\d_qfsinf.asm. */
  231. // { ERROR_MOD_NOT_FOUND, },
  232. // { ERROR_PROC_NOT_FOUND, },
  233. // { ERROR_WAIT_NO_CHILDREN, },
  234. // { ERROR_CHILD_NOT_COMPLETE, },
  235. // { ERROR_DIRECT_ACCESS_HANDLE, },
  236. /* for direct disk access */
  237. /* handles */
  238. // { ERROR_NEGATIVE_SEEK, },
  239. /* with negitive offset */
  240. // { ERROR_SEEK_ON_DEVICE, },
  241. /* on device or pipe */
  242. { ERROR_BAD_PATHNAME, STATUS_OBJECT_PATH_INVALID }, //*
  243. /*
  244. * Error codes 230 - 249 are reserved for MS Networks
  245. */
  246. { ERROR_BAD_PIPE, STATUS_INVALID_PARAMETER },
  247. { ERROR_PIPE_BUSY, STATUS_PIPE_NOT_AVAILABLE },
  248. { ERROR_NO_DATA, STATUS_PIPE_EMPTY },
  249. { ERROR_PIPE_NOT_CONNECTED, STATUS_PIPE_DISCONNECTED },
  250. { ERROR_MORE_DATA, STATUS_BUFFER_OVERFLOW },
  251. { ERROR_VC_DISCONNECTED, STATUS_VIRTUAL_CIRCUIT_CLOSED },
  252. };
  253. #define NUM_ERRORS sizeof(Error_Map) / sizeof(Error_Map[0])
  254. //
  255. // The debug trace level
  256. //
  257. #define Dbg (DEBUG_TRACE_CONVERT)
  258. #ifdef ALLOC_PRAGMA
  259. #pragma alloc_text( PAGE, NtToNwShareFlags )
  260. #pragma alloc_text( PAGE, NtAttributesToNwAttributes )
  261. #ifndef QFE_BUILD
  262. #pragma alloc_text( PAGE1, pNwErrorToNtStatus )
  263. #pragma alloc_text( PAGE1, NwBurstResultToNtStatus )
  264. #pragma alloc_text( PAGE1, NwConnectionStatusToNtStatus )
  265. #pragma alloc_text( PAGE1, NwDateTimeToNtTime )
  266. #pragma alloc_text( PAGE1, NwNtTimeToNwDateTime )
  267. #endif
  268. #endif
  269. #if 0 // Not pageable
  270. // see ifndef QFE_BUILD above
  271. #endif
  272. UCHAR
  273. NtToNwShareFlags(
  274. ULONG DesiredAccess,
  275. ULONG NtShareFlags
  276. )
  277. /*++
  278. Routine Description:
  279. This routine maps a NT desired/share access to Netware share flag bits.
  280. Arguments:
  281. DesiredAccess - Desired access for open as specified in the read IRP.
  282. NtShareFlags - The NT share flags from the create IRP.
  283. Return Value:
  284. Netware share mode.
  285. --*/
  286. {
  287. UCHAR NwShareFlags = 0;
  288. ULONG lDesiredAccess;
  289. PAGED_CODE();
  290. //
  291. // Ignore share delete, since we can't do anything with it.
  292. //
  293. switch ( NtShareFlags & (FILE_SHARE_READ | FILE_SHARE_WRITE) ) {
  294. case 0:
  295. // ---- Multi-user code merge -------
  296. // AJ: NW_OPEN_EXCLUSIVE under NT means NW_DENY_WRITE | NW_DENY_READ.
  297. // NW_OPEN_EXCLUSIVE flag is mapped to AR_COMPITIBLITY under NetWare. Which does
  298. // not serve the purpose as if it is under NT. Under Netware we have AR_DENY_READ and
  299. // AR_DENY_WRITE which maps to NW_DENY_READ and NW_DENY_WRITE respectivly.
  300. NwShareFlags = NW_DENY_WRITE | NW_DENY_READ;
  301. // NwShareFlags = NW_OPEN_EXCLUSIVE;
  302. break;
  303. case FILE_SHARE_READ:
  304. NwShareFlags = NW_DENY_WRITE;
  305. break;
  306. case FILE_SHARE_WRITE:
  307. NwShareFlags = NW_DENY_READ;
  308. break;
  309. case FILE_SHARE_WRITE | FILE_SHARE_READ:
  310. NwShareFlags = 0;
  311. }
  312. //
  313. // Treat append the same as write.
  314. //
  315. if ( DesiredAccess & FILE_APPEND_DATA) {
  316. lDesiredAccess = DesiredAccess | FILE_WRITE_DATA;
  317. } else {
  318. lDesiredAccess = DesiredAccess;
  319. }
  320. switch ( lDesiredAccess & (FILE_EXECUTE | FILE_WRITE_DATA | FILE_READ_DATA) ) {
  321. case (FILE_EXECUTE | FILE_WRITE_DATA | FILE_READ_DATA):
  322. case (FILE_EXECUTE | FILE_WRITE_DATA):
  323. NwShareFlags |= NW_OPEN_EXCLUSIVE | NW_OPEN_FOR_WRITE | NW_OPEN_FOR_READ;
  324. break;
  325. case (FILE_EXECUTE | FILE_READ_DATA):
  326. case (FILE_EXECUTE):
  327. NwShareFlags |= NW_OPEN_EXCLUSIVE | NW_OPEN_FOR_READ;
  328. break;
  329. case (FILE_WRITE_DATA | FILE_READ_DATA):
  330. NwShareFlags |= NW_OPEN_FOR_WRITE | NW_OPEN_FOR_READ;
  331. break;
  332. case (FILE_WRITE_DATA):
  333. NwShareFlags |= NW_OPEN_FOR_WRITE;
  334. break;
  335. default:
  336. NwShareFlags |= NW_OPEN_FOR_READ;
  337. break;
  338. }
  339. if (NwShareFlags & NW_OPEN_EXCLUSIVE) {
  340. //
  341. // Remove the NW_DENY_* flags if exclusive is already specified since
  342. // this interferes with the shareable flag.
  343. //
  344. return( NwShareFlags & ~(NW_DENY_READ | NW_DENY_WRITE) );
  345. }
  346. return( NwShareFlags );
  347. }
  348. UCHAR
  349. NtAttributesToNwAttributes(
  350. ULONG FileAttributes
  351. )
  352. /*++
  353. Routine Description:
  354. This routine maps a NT attributes mask to a Netware mask.
  355. Arguments:
  356. DesiredAccess - Desired access for open as specified in the read IRP.
  357. Return Value:
  358. Netware share mode.
  359. --*/
  360. {
  361. return( (UCHAR)FileAttributes & 0x3F );
  362. }
  363. NTSTATUS
  364. pNwErrorToNtStatus(
  365. UCHAR NwError
  366. )
  367. /*++
  368. Routine Description:
  369. This routine converts a Netware error code to an NT status code.
  370. Arguments:
  371. NwError - The netware error.
  372. Return Value:
  373. NTSTATUS - The converted status.
  374. --*/
  375. {
  376. int i;
  377. ASSERT(NwError != 0);
  378. //
  379. // Errors 2 through 127 are mapped as DOS errors.
  380. //
  381. if ( NwError > 1 && NwError < 128 ) {
  382. return( BASE_DOS_ERROR + NwError );
  383. }
  384. //
  385. // For other errors, search the table for the matching error number.
  386. //
  387. for ( i = 0; i < NUM_ERRORS; i++ ) {
  388. if ( Error_Map[i].NetError == NwError ) {
  389. return( Error_Map[i].ResultingStatus );
  390. }
  391. }
  392. DebugTrace( 0, 0, "No error mapping for error %d\n", NwError );
  393. #ifdef NWDBG
  394. Error( EVENT_NWRDR_NETWORK_ERROR, (NTSTATUS)0xC0010000 | NwError, NULL, 0, 0 );
  395. #endif
  396. return( (NTSTATUS)0xC0010000 | NwError );
  397. }
  398. NTSTATUS
  399. NwBurstResultToNtStatus(
  400. ULONG Result
  401. )
  402. /*++
  403. Routine Description:
  404. This routine converts a Netware burst result code to an NT status code.
  405. Arguments:
  406. Result - The netware burst result.
  407. Return Value:
  408. NTSTATUS - The converted status.
  409. --*/
  410. {
  411. NTSTATUS Status;
  412. //
  413. // the 3 high order bits should not be set. but if they are,
  414. // we return an error.
  415. //
  416. if (Result & 0xFFFFFF00)
  417. return( STATUS_UNEXPECTED_NETWORK_ERROR );
  418. switch ( Result ) {
  419. case 0:
  420. case 3: // No data
  421. Status = STATUS_SUCCESS;
  422. break;
  423. case 1:
  424. Status = STATUS_DISK_FULL;
  425. break;
  426. case 2: // I/O error
  427. Status = STATUS_UNEXPECTED_IO_ERROR;
  428. break;
  429. default:
  430. Status = NwErrorToNtStatus( (UCHAR)Result );
  431. break;
  432. }
  433. return( Status );
  434. }
  435. NTSTATUS
  436. NwConnectionStatusToNtStatus(
  437. UCHAR NwStatus
  438. )
  439. /*++
  440. Routine Description:
  441. This routine converts a Netware connection status code to an NT
  442. status code.
  443. Arguments:
  444. NwStatus - The netware connection status.
  445. Return Value:
  446. NTSTATUS - The converted status.
  447. --*/
  448. {
  449. if ( (NwStatus & 1) == 0 ) {
  450. return STATUS_SUCCESS;
  451. } else {
  452. return STATUS_REMOTE_DISCONNECT;
  453. }
  454. }
  455. LARGE_INTEGER
  456. NwDateTimeToNtTime (
  457. IN USHORT UDate,
  458. IN USHORT UTime
  459. )
  460. /*++
  461. Routine Description:
  462. This routine converts an NCP time to an NT time structure.
  463. Arguments:
  464. Time - Supplies the time of day to convert
  465. Date - Supplies the day of the year to convert
  466. Return Value:
  467. LARGE_INTEGER - Time structure describing input time.
  468. --*/
  469. {
  470. TIME_FIELDS TimeFields;
  471. LARGE_INTEGER OutputTime;
  472. NCP_DATE Date = *(NCP_DATE *)&UDate;
  473. NCP_TIME Time = *(NCP_TIME *)&UTime;
  474. if ( Date.Ushort == 0 && Time.Ushort == 0 ) {
  475. //
  476. // The file time stamp is zero. Do not return a file time of
  477. // zero, since this will be biased to a negative time (due to
  478. // time zone fixup), and no one will be able to display it
  479. // correctly. Instead, we "randomly" pick Jan 01, 1980 @ 12:00am
  480. // as the file time.
  481. //
  482. // We assume that the netware server is in our time zone.
  483. RtlSecondsSince1980ToTime(0, &OutputTime);
  484. } else {
  485. TimeFields.Year = Date.Struct.Year + (USHORT )1980;
  486. TimeFields.Month = Date.Struct.Month;
  487. TimeFields.Day = Date.Struct.Day;
  488. TimeFields.Hour = Time.Struct.Hours;
  489. TimeFields.Minute = Time.Struct.Minutes;
  490. TimeFields.Second = Time.Struct.TwoSeconds*(USHORT )2;
  491. TimeFields.Milliseconds = 0;
  492. //
  493. // Make sure that the times specified in the packet are reasonable
  494. // before converting them.
  495. //
  496. if (TimeFields.Year < 1601) {
  497. TimeFields.Year = 1601;
  498. }
  499. if (TimeFields.Month > 12) {
  500. TimeFields.Month = 12;
  501. }
  502. if (TimeFields.Hour >= 24) {
  503. TimeFields.Hour = 23;
  504. }
  505. if (TimeFields.Minute >= 60) {
  506. TimeFields.Minute = 59;
  507. }
  508. if (TimeFields.Second >= 60) {
  509. TimeFields.Second = 59;
  510. }
  511. if (!RtlTimeFieldsToTime(&TimeFields, &OutputTime)) {
  512. OutputTime.QuadPart = 0;
  513. return OutputTime;
  514. }
  515. }
  516. // Convert to UTC for the system.
  517. ExLocalTimeToSystemTime(&OutputTime, &OutputTime);
  518. return OutputTime;
  519. }
  520. NTSTATUS
  521. NwNtTimeToNwDateTime (
  522. IN LARGE_INTEGER NtTime,
  523. IN PUSHORT NwDate,
  524. IN PUSHORT NwTime
  525. )
  526. /*++
  527. Routine Description:
  528. This routine converts an NT time structure to an NCP time.
  529. Arguments:
  530. NtTime - Supplies to NT Time to convert.
  531. NwDate - Returns the Netware format date.
  532. NwTime - Returns the Netware format time.
  533. Return Value:
  534. The status of the operation.
  535. --*/
  536. {
  537. TIME_FIELDS TimeFields;
  538. NCP_DATE Date;
  539. NCP_TIME Time;
  540. if (NtTime.QuadPart == 0) {
  541. Time.Ushort = Date.Ushort = 0;
  542. } else {
  543. LARGE_INTEGER LocalTime;
  544. // We assume that the netware server is in our time zone.
  545. ExSystemTimeToLocalTime( &NtTime, &LocalTime );
  546. RtlTimeToTimeFields( &LocalTime, &TimeFields );
  547. if (TimeFields.Year < 1980 || TimeFields.Year > (1980 + 127) ) {
  548. return( STATUS_INVALID_PARAMETER );
  549. }
  550. Date.Struct.Year = (USHORT )(TimeFields.Year - 1980);
  551. Date.Struct.Month = TimeFields.Month;
  552. Date.Struct.Day = TimeFields.Day;
  553. Time.Struct.Hours = TimeFields.Hour;
  554. Time.Struct.Minutes = TimeFields.Minute;
  555. //
  556. // When converting from a higher granularity time to a lesser
  557. // granularity time (seconds to 2 seconds), always round up
  558. // the time, don't round down.
  559. //
  560. Time.Struct.TwoSeconds = TimeFields.Second / 2;
  561. }
  562. *NwDate = *( USHORT *)&Date;
  563. *NwTime = *( USHORT *)&Time;
  564. return( STATUS_SUCCESS );
  565. }