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.

676 lines
23 KiB

  1. /*++
  2. Copyright (c) 1988-1999 Microsoft Corporation
  3. Module Name:
  4. cinfo.c
  5. Abstract:
  6. Information command support
  7. --*/
  8. #include "cmd.h"
  9. #define TYPEBUFSIZE 80
  10. #define TYPEREADSIZE 512
  11. extern UINT CurrentCP;
  12. extern unsigned DosErr ;
  13. extern unsigned tywild; /* @@5@J1 type wild cards */
  14. extern TCHAR CurDrvDir[] ;
  15. extern TCHAR VolSrch[] ; /* M006 - Search string for Volume ID */
  16. extern TCHAR AppendStr[] ;
  17. extern TCHAR Fmt26[], Fmt25[];
  18. extern unsigned LastRetCode;
  19. extern BOOL CtrlCSeen;
  20. struct FSVol {
  21. unsigned long SerNum ; /* Volume serial number */
  22. TCHAR len ; /* Volume name len (excludes \0) */
  23. TCHAR name[257] ; /* Volume name asciz */
  24. };
  25. int ZScanA(BOOL flag, PCHAR buf, PULONG buflen, PULONG skip);
  26. /**************** START OF SPECIFICATIONS ***********************/
  27. /* */
  28. /* SUBROUTINE NAME: eDirectory */
  29. /* */
  30. /* DESCRIPTIVE NAME: Begin execution of the DIR command */
  31. /* */
  32. /* FUNCTION: To list out the files on a disk. eDirectory will */
  33. /* be called whenever the user enters the DIR command */
  34. /* on the command line. DIR will continue if it */
  35. /* encounters an invalid argument. */
  36. /* */
  37. /* NOTES: */
  38. /* */
  39. /* ENTRY POINT: eDirectory */
  40. /* LINKAGE: Near */
  41. /* */
  42. /* INPUT: n - the parse tree node containing the DIR command */
  43. /* */
  44. /* EXIT-NORMAL: return SUCCESS if no errors occur */
  45. /* */
  46. /* EXIT-ERROR: return FAILURE otherwise */
  47. /* */
  48. /* EFFECTS: None. */
  49. /* */
  50. /* INTERNAL REFERENCES: */
  51. /* ROUTINES: */
  52. /* Dir - lists out the files in a directory */
  53. /* */
  54. /* EXTERNAL REFERENCES: */
  55. /* ROUTINES: */
  56. /* */
  57. /**************** END OF SPECIFICATIONS *************************/
  58. int eDirectory(n)
  59. struct cmdnode *n ;
  60. {
  61. return(LastRetCode = Dir(n->argptr)) ;
  62. }
  63. /*** eType - begin the execution of a Type command
  64. *
  65. * Purpose:
  66. * To type the contents of an arbitrary number of files.
  67. *
  68. * int eType(struct cmdnode *n)
  69. *
  70. * Args:
  71. * n - the parse tree note containing the type command
  72. *
  73. * Returns:
  74. * SUCCESS if all of the files were successfully typed.
  75. * FAILURE otherwise.
  76. *
  77. */
  78. int eType(n)
  79. struct cmdnode *n ;
  80. {
  81. //
  82. // Removed LTA_NOMATCH from flags. This caused a *.xxx to call the TyWork
  83. // function which would think that *.xxx is a file and try to open it.
  84. //
  85. return(LastRetCode = LoopThroughArgs(n->argptr, TyWork, LTA_EXPAND | LTA_CONT | LTA_NOMATCH)) ;
  86. }
  87. /*** TyWork - display a file
  88. *
  89. * Purpose:
  90. * Write the contents of the file specified in fspec to stdout.
  91. * Output ends when all of fspec has been written or a ^Z is found in
  92. * fspec.
  93. *
  94. * int TyWork(TCHAR *fspec)
  95. *
  96. * Args:
  97. * fspec - the name of the file to write out
  98. *
  99. * Returns:
  100. * SUCCESS if the file was written.
  101. * FAILURE otherwise, such as inability to allocate a temporary buffer
  102. */
  103. int TyWork(TCHAR *fspec) {
  104. TCHAR fspec_temp[MAX_PATH];
  105. TCHAR TypeBufW[TYPEREADSIZE*3];
  106. CHAR TypeBuf[TYPEREADSIZE+1];
  107. ULONG result;
  108. BOOL flag;
  109. const TCHAR *bptr;
  110. ULONG fDevice = 0;
  111. ULONG maxbytes = 0xFFFFFFFF ; // max file size
  112. ULONG bytestoctlz ; // Number of bytes read
  113. ULONG bytesread ; // Number of bytes read
  114. ULONG byteswrit ; // Number of bytes read
  115. ULONG brcopy ; // Bytes to copy
  116. CRTHANDLE fh ; // File handle
  117. int first_read; // first read on file for wild
  118. int TypeBufSize;
  119. int rc;
  120. LONG bWrite;
  121. CHAR *pType;
  122. #ifdef UNICODE
  123. WCHAR wc;
  124. BOOL fUnicode=FALSE;
  125. #endif // UNICODE
  126. TypeBufSize = TYPEREADSIZE;
  127. first_read = TRUE; /* set flag to test for wilds @@5@J1 */
  128. DEBUG((ICGRP, TYLVL, "TYWORK: fspec = `%ws'", fspec)) ;
  129. if ((fh = Copen(fspec, O_RDONLY)) == BADHANDLE) {
  130. bptr = MyGetEnvVarPtr(AppendStr);
  131. if ( bptr != NULL &&
  132. SearchPath( bptr,
  133. (TCHAR *)fspec,
  134. NULL,
  135. (unsigned)MAX_PATH,
  136. (TCHAR *)fspec_temp,
  137. NULL ) != 0) {
  138. fh = Copen(fspec_temp, O_RDONLY);
  139. }
  140. }
  141. if ( fh == BADHANDLE ) {
  142. if (DosErr == ERROR_INVALID_NAME) {
  143. DosErr = ERROR_FILE_NOT_FOUND;
  144. }
  145. PrtErr(DosErr) ;
  146. rc = FAILURE;
  147. goto TypeExit;
  148. }
  149. /************************************************************/
  150. /* M004 - Added code to get max file size if not device */
  151. /************************************************************/
  152. bptr = (TCHAR*)TypeBuf; /* Copy of original pointer*/
  153. if (!FileIsDevice(fh)) {
  154. maxbytes = GetFileSize(CRTTONT(fh), NULL) ; /* Get file size */
  155. SetFilePointer(CRTTONT(fh), 0L, NULL, FILE_BEGIN) ; /* Return pointer*/
  156. fDevice = 1 ; /* Set no device flag */
  157. DEBUG((ICGRP,TYLVL,"TYWORK: Is file, size=%d", maxbytes)) ;
  158. }
  159. do {
  160. if (CtrlCSeen) {
  161. Cclose(fh) ;
  162. rc = FAILURE;
  163. goto TypeExit;
  164. }
  165. if (!ReadFile(CRTTONT(fh), TypeBuf, TypeBufSize, (LPDWORD)&bytesread, NULL)) {
  166. DosErr = GetLastError();
  167. PutStdErr(DosErr, NOARGS);
  168. break;
  169. }
  170. if (bytesread == 0) {
  171. break;
  172. }
  173. #ifdef UNICODE
  174. if (first_read) {
  175. fUnicode = *(LPWSTR)TypeBuf == BYTE_ORDER_MARK;
  176. if (fUnicode) {
  177. bytesread -= sizeof( TCHAR );
  178. MoveMemory( TypeBuf, TypeBuf + sizeof( TCHAR ), bytesread );
  179. }
  180. }
  181. #endif // UNICODE
  182. bytestoctlz = bytesread;
  183. #ifdef UNICODE
  184. if (fUnicode) {
  185. if (first_read) {
  186. DEBUG((ICGRP, TYLVL, "TYWORK: file is unicode")) ;
  187. }
  188. brcopy = bytesread / sizeof(TCHAR);
  189. } else
  190. #endif // UNICODE
  191. if (FileIsConsole(STDOUT)
  192. #ifdef UNICODE
  193. || fOutputUnicode
  194. #endif // UNICODE
  195. ) {
  196. PCHAR pch = TypeBuf;
  197. brcopy = bytesread;
  198. while (brcopy > 0) {
  199. if (is_dbcsleadchar(*pch)) {
  200. pch++;
  201. if (--brcopy == 0) {
  202. if (!ReadFile(CRTTONT(fh), pch, 1, &brcopy, NULL)) {
  203. DosErr = GetLastError();
  204. PutStdErr(DosErr, NOARGS);
  205. Cclose(fh) ;
  206. rc = SUCCESS;
  207. goto TypeExit;
  208. }
  209. bytesread++;
  210. bytestoctlz = bytesread;
  211. break;
  212. }
  213. }
  214. pch++;
  215. brcopy--;
  216. }
  217. result = 0;
  218. flag = ZScanA(TRUE, (PCHAR)TypeBuf, &bytestoctlz, &result);
  219. DEBUG((ICGRP, TYLVL, "TYWORK: converting %d bytes to unicode", flag?bytesread:bytestoctlz)) ;
  220. if ( (!flag) && (bytestoctlz == 0) )
  221. break;
  222. brcopy = MultiByteToWideChar(CurrentCP, 0,
  223. (LPCSTR)TypeBuf, flag?bytesread:bytestoctlz,
  224. (LPWSTR)TypeBufW, TypeBufSize*2);
  225. if (brcopy == 0) {
  226. DEBUG((ICGRP, TYLVL, "TYWORK: Error converting to Unicode: %d", GetLastError())) ;
  227. brcopy = TypeBufSize*2;
  228. }
  229. bptr = TypeBufW;
  230. } else {
  231. brcopy = bytesread;
  232. }
  233. if (first_read) {
  234. if (tywild)
  235. PutStdErr(MSG_TYPE_FILENAME, ONEARG, fspec);
  236. first_read = FALSE;
  237. }
  238. DEBUG((ICGRP, TYLVL, "TYWORK: bytesread = %d, brcopy = %d", bytesread, brcopy)) ;
  239. bWrite = brcopy;
  240. pType = (CHAR *)bptr;
  241. while ( bWrite > 0 ) {
  242. ULONG bToWrite = min( TYPEBUFSIZE, bWrite );
  243. if ( bToWrite == 0 ) {
  244. break;
  245. }
  246. if (CtrlCSeen) {
  247. Cclose(fh) ;
  248. rc = FAILURE;
  249. goto TypeExit;
  250. }
  251. if (FileIsConsole(STDOUT)) {
  252. DEBUG((ICGRP, TYLVL, "TYWORK: Writing to console")) ;
  253. flag = WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), pType, bToWrite, &byteswrit, NULL);
  254. if (flag == 0 || byteswrit != bToWrite) {
  255. goto try_again;
  256. }
  257. bWrite -= byteswrit;
  258. byteswrit *= sizeof(TCHAR);
  259. pType += byteswrit;
  260. #ifdef UNICODE
  261. } else if (fOutputUnicode || fUnicode) {
  262. if ( fUnicode ) {
  263. wc = *((TCHAR*)pType + bToWrite);
  264. *((TCHAR*)pType + bToWrite) = UNICODE_NULL;
  265. }
  266. DEBUG((ICGRP, TYLVL, "TYWORK: Writing unicode text to file")) ;
  267. flag = MyWriteFile(
  268. STDOUT, /* device */
  269. pType, /* bytes */
  270. bToWrite * sizeof(TCHAR), /* bytes to write */
  271. &byteswrit); /* bytes actually written */
  272. if ( fUnicode ) {
  273. *((TCHAR*)pType + bToWrite) = wc;
  274. }
  275. bWrite -= byteswrit/sizeof(TCHAR);
  276. pType += byteswrit;
  277. #endif // UNICODE
  278. } else {
  279. try_again:
  280. DEBUG((ICGRP, TYLVL, "TYWORK: Writing dbcs text to file")) ;
  281. flag = WriteFile(CRTTONT(STDOUT), pType, bToWrite, &byteswrit, NULL);
  282. bWrite -= byteswrit;
  283. pType += byteswrit;
  284. byteswrit *= sizeof(TCHAR);
  285. }
  286. DEBUG((ICGRP, TYLVL, "TYWORK: flag = %d, byteswrit = %d", flag, byteswrit)) ;
  287. if (flag == 0 || byteswrit != bToWrite*sizeof(TCHAR)) {
  288. DosErr = GetLastError();
  289. if (!DosErr) {
  290. DosErr = ERROR_DISK_FULL ;
  291. }
  292. if (FileIsDevice(STDOUT)) {
  293. PutStdErr(ERROR_WRITE_FAULT, NOARGS);
  294. } else {
  295. if (FileIsPipe(STDOUT)) {
  296. PutStdErr(MSG_CMD_INVAL_PIPE, NOARGS);
  297. } else {
  298. PrtErr(DosErr);
  299. }
  300. Cclose(fh);
  301. rc = FAILURE;
  302. goto TypeExit;
  303. }
  304. }
  305. }
  306. if (fDevice) { /* If not device */
  307. /* Get new position ptr */
  308. fDevice = SetFilePointer(CRTTONT(fh), 0, NULL, FILE_CURRENT);
  309. }
  310. /*************************************************/
  311. /* Added check below for current file position */
  312. /* at original EOF */
  313. /*************************************************/
  314. } while((bytesread == bytestoctlz) && (maxbytes > fDevice));
  315. Cclose(fh) ;
  316. rc = SUCCESS;
  317. TypeExit:
  318. return(rc) ;
  319. }
  320. /*** eVersion - execute the Version command
  321. *
  322. * Purpose:
  323. * To print DOS version information.
  324. *
  325. * int eVersion(struct cmdnode *n)
  326. *
  327. * Args:
  328. * n - the parse tree node containing the version command. N will be NULL
  329. * if eVersion was called from PrintPrompt().
  330. *
  331. * Returns:
  332. * SUCCESS always.
  333. *
  334. */
  335. int
  336. eVersion(
  337. struct cmdnode *n
  338. )
  339. {
  340. TCHAR VersionFormat[32];
  341. GetVersionString( VersionFormat, sizeof( VersionFormat ) / sizeof( VersionFormat[0] ));
  342. if (n)
  343. cmd_printf( CrLf );
  344. PutStdOut( MSG_MS_DOS_VERSION,
  345. ONEARG,
  346. VersionFormat );
  347. if (n)
  348. cmd_printf( CrLf );
  349. return(LastRetCode = SUCCESS) ;
  350. }
  351. /**************** START OF SPECIFICATIONS ***********************/
  352. /* */
  353. /* SUBROUTINE NAME: eVolume */
  354. /* */
  355. /* DESCRIPTIVE NAME: Begin execution of the VOL command */
  356. /* */
  357. /* FUNCTION: eVolume will print out the volume label and serial */
  358. /* number for an arbitrary number of drives, and will */
  359. /* continue if it encounters an invalid argument. */
  360. /* This routine is called when the user enters VOL */
  361. /* on the command line. */
  362. /* */
  363. /* NOTES: */
  364. /* */
  365. /* ENTRY POINT: eVolume */
  366. /* LINKAGE: Near */
  367. /* */
  368. /* INPUT: n - a parse tree node containing the VOL command */
  369. /* */
  370. /* EXIT-NORMAL: returns SUCCESS if the command was well formed, */
  371. /* and was executed successfully. */
  372. /* */
  373. /* EXIT-ERROR: returns FAILURE otherwise. */
  374. /* */
  375. /* EFFECTS: None. */
  376. /* */
  377. /* INTERNAL REFERENCES: */
  378. /* ROUTINES: */
  379. /* LoopThroughArgs - breaks up command line, calls VolWork */
  380. /* */
  381. /* EXTERNAL REFERENCES: */
  382. /* ROUTINES: */
  383. /* */
  384. /**************** END OF SPECIFICATIONS *************************/
  385. int eVolume(n)
  386. struct cmdnode *n ;
  387. {
  388. return(LastRetCode = LoopThroughArgs(n->argptr, VolWork, LTA_CONT|LTA_NULLOK)) ;
  389. }
  390. /**************** START OF SPECIFICATIONS ***********************/
  391. /* */
  392. /* SUBROUTINE NAME: VolWork */
  393. /* */
  394. /* DESCRIPTIVE NAME: Display the volume ID of a drive */
  395. /* */
  396. /* FUNCTION: VolWork will print the volume label and serial */
  397. /* number of a specific drive. */
  398. /* */
  399. /* NOTES: */
  400. /* */
  401. /* ENTRY POINT: VolWork */
  402. /* LINKAGE: Near */
  403. /* */
  404. /* INPUT: drvspec - a pointer to a character specifying the */
  405. /* drive to print the information for. If the */
  406. /* character is null, the information for the */
  407. /* current drive is displayed. */
  408. /* */
  409. /* EXIT-NORMAL: returns SUCCESS if the command was executed */
  410. /* successfully */
  411. /* */
  412. /* EXIT-ERROR: returns FAILURE otherwise */
  413. /* */
  414. /* EFFECTS: None. */
  415. /* */
  416. /* INTERNAL REFERENCES: */
  417. /* ROUTINES: */
  418. /* PutStdOut - Writes output to standard out */
  419. /* PutStdErr - Writes output to standard error */
  420. /* */
  421. /* EXTERNAL REFERENCES: */
  422. /* ROUTINES: */
  423. /* DOSQFSINFO */
  424. /* */
  425. /**************** END OF SPECIFICATIONS *************************/
  426. int VolWork(drvspec)
  427. TCHAR *drvspec ;
  428. {
  429. struct FSVol vol ;
  430. unsigned DNum ;
  431. TCHAR c ;
  432. TCHAR VolumeRoot[] = TEXT(" :\\");
  433. DWORD Vsn[2];
  434. BOOL b;
  435. DEBUG((ICGRP, VOLVL, "VOLWORK: drvspec = `%ws'", drvspec)) ;
  436. if (*drvspec == NULLC) {
  437. DNum = 0 ;
  438. c = (TCHAR) _totupper(CurDrvDir[0]) ;
  439. } else if ((mystrlen(drvspec) == 2) &&
  440. *(drvspec+1) == COLON &&
  441. _istalpha(*drvspec)) {
  442. c = (TCHAR) _totupper(*drvspec) ;
  443. DNum = (unsigned)(c - 0x40) ;
  444. } else {
  445. cmd_printf(CrLf);
  446. PutStdErr(ERROR_INVALID_DRIVE, NOARGS) ; /* M013 */
  447. return(FAILURE) ;
  448. } ;
  449. VolumeRoot[0] = c;
  450. b = GetVolumeInformation(
  451. VolumeRoot,
  452. vol.name,
  453. sizeof( vol.name ) / sizeof( TCHAR ),
  454. Vsn,
  455. NULL,
  456. NULL,
  457. NULL,
  458. 0);
  459. if (!b) {
  460. DEBUG((ICGRP, VOLVL, "VOLWORK: GetVolumeInformation ret'd %d", GetLastError())) ;
  461. cmd_printf(CrLf);
  462. if (GetLastError() == ERROR_NOT_READY)
  463. PutStdErr(ERROR_NOT_READY, NOARGS) ;
  464. else
  465. PutStdErr(GetLastError(), NOARGS) ; /* @@5a */
  466. return(FAILURE) ;
  467. } else {
  468. if (b && vol.name[0]) {
  469. /* M013 */ PutStdOut(MSG_DR_VOL_LABEL, TWOARGS,
  470. argstr1( TEXT("%c"), (ULONG_PTR)c),
  471. vol.name ) ;
  472. }
  473. else {
  474. /* M013 */ PutStdOut(MSG_HAS_NO_LABEL, ONEARG,
  475. argstr1( TEXT("%c"), (ULONG_PTR)c)) ;
  476. }
  477. /* @@5 */ if (b) { // FIX, FIX
  478. TCHAR Buffer[128];
  479. _sntprintf(Buffer, 128, Fmt26,
  480. (Vsn[0] & 0xffff0000)>>16, (Vsn[0] & 0xffff));
  481. Buffer[127] = TEXT( '\0' );
  482. PutStdOut(MSG_DR_VOL_SERIAL, ONEARG, Buffer );
  483. /* @@5 */ }
  484. } ;
  485. return(SUCCESS) ;
  486. }
  487. /****************************************************************
  488. *
  489. * ZScanA - scan data in an arbitrary segment for ^Zs
  490. *
  491. * Purpose:
  492. * If flag is on, scan buffer for a ^Z. If it is found, update the
  493. * buffer length and return 0. Otherwise return -1.
  494. * Double byte characters are taken into account.
  495. *
  496. * int ZScanA(int flag, long buffer, unsigned *buflenptr, int *skip_first)
  497. *
  498. * Args:
  499. * flag - nonzero if any scanning is to be done
  500. * buffer - a long pointer to the buffer to use
  501. * buflenptr - ptr to the length of buffer
  502. * skip_first - ptr to an integer. The initial value of *skip_first
  503. * must be 0 on the first call when scanning a file. There
  504. * after, the caller leaves *skip_first alone. ZScan uses
  505. * the variable to remember if the first byte of the next
  506. * buffer is going to be the second have of a double
  507. * byte character.
  508. *
  509. * Returns:
  510. * See above.
  511. *
  512. * Notes:
  513. * This routine will need to be modified once the MMU code is in the DOS.
  514. * macro is defined in cmd.h.
  515. *
  516. *
  517. * ZScanA
  518. * if (flag) then
  519. * buffer = buffer + *skip_first
  520. * dbcs_flag = 0
  521. * count = *buflenptr - *skip_first
  522. * use rep scanb to find first ^Z in buffer
  523. * if (no ^z was found)
  524. * goto FZSNoZ
  525. * do {
  526. * count++;
  527. * buffer--;
  528. * } until (*buffer < 0x80 || count = *buflenptr);
  529. * while (--count > 0) loop
  530. * if (dbcs_flag == 0) then
  531. * if (*buffer == ^Z) then
  532. * *buflenptr = count
  533. * return(0)
  534. * else if (*buffer is a dbcs_lead_char) then
  535. * dbcs_flag = 1
  536. * endif
  537. * endif
  538. * else
  539. * dbcs_flag = 0
  540. * buffer = buffer + 1
  541. * count = count - 1
  542. * end loop
  543. * *skip_first = dbcs_flag
  544. * endif
  545. *FZSNoZ:
  546. * return(-1)
  547. *----
  548. ****************************************************************/
  549. int
  550. ZScanA(BOOL flag, PCHAR buf, PULONG buflen, PULONG skip)
  551. {
  552. PCHAR pbuf = buf,
  553. bufend;
  554. CHAR c0 = '\0';
  555. if ( flag ) {
  556. pbuf += *skip;
  557. bufend = buf + *buflen - *skip;
  558. while (pbuf < bufend) {
  559. if (is_dbcsleadchar(c0=*pbuf))
  560. pbuf++;
  561. if (c0 == CTRLZ)
  562. break;
  563. pbuf++;
  564. }
  565. if (c0 == CTRLZ) {
  566. // *buflen = pbuf+1 - buf;
  567. *buflen = (ULONG)(pbuf - buf);
  568. *skip = 0;
  569. return(0);
  570. }
  571. else {
  572. *skip = (ULONG)(pbuf - bufend);
  573. }
  574. }
  575. return(-1);
  576. }