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.

1495 lines
41 KiB

  1. /*************************************************************************
  2. *
  3. * NWAPI3.C
  4. *
  5. * NetWare routines ported from DOS
  6. *
  7. * Copyright (c) 1995 Microsoft Corporation
  8. *
  9. * $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\NWAPI3.C $
  10. *
  11. * Rev 1.4 18 Apr 1996 16:52:14 terryt
  12. * Various enhancements
  13. *
  14. * Rev 1.3 10 Apr 1996 14:23:20 terryt
  15. * Hotfix for 21181hq
  16. *
  17. * Rev 1.5 13 Mar 1996 18:49:28 terryt
  18. * Support directory maps
  19. *
  20. * Rev 1.4 12 Mar 1996 19:55:10 terryt
  21. * Relative NDS names and merge
  22. *
  23. * Rev 1.2 22 Dec 1995 14:26:02 terryt
  24. * Add Microsoft headers
  25. *
  26. * Rev 1.1 22 Nov 1995 15:41:56 terryt
  27. * Fix MAP ROOT of search drives
  28. *
  29. * Rev 1.0 15 Nov 1995 18:07:38 terryt
  30. * Initial revision.
  31. *
  32. * Rev 1.3 25 Aug 1995 16:23:22 terryt
  33. * Capture support
  34. *
  35. * Rev 1.2 26 Jul 1995 16:02:08 terryt
  36. * Allow deletion of current drive
  37. *
  38. * Rev 1.1 23 Jun 1995 09:49:22 terryt
  39. * Add error message for mapping over MS network drive
  40. *
  41. * Rev 1.0 15 May 1995 19:10:54 terryt
  42. * Initial revision.
  43. *
  44. *************************************************************************/
  45. /*
  46. Module Name:
  47. nwapi3.c
  48. Abstract:
  49. can :
  50. - view current mapping
  51. - create/change a drive mapping
  52. - create/change a search drive mapping
  53. - map a drive to a fake root
  54. - map the next available drive
  55. SYNTAX (Command line)
  56. View current mapping.
  57. MAP [drive:]
  58. Create or change network drive mappings
  59. MAP path
  60. MAP drive:=[drive:|path]
  61. MAP [DEL[ete] | REM[ove]] drive:
  62. Create or change search dirve mappings
  63. MAP [INS[ert]] drive:=[drive:|path]
  64. Map a drive to a fake root directory
  65. MAP ROOT drive:=[drive:|path]
  66. Map the next available dirve
  67. MAP N[ext] [drive:|path]
  68. Author : Thierry TABARD (thierryt)
  69. Revision history :
  70. - 03/10/94 thierryt started
  71. - 05/13/94 congpay rewrote.
  72. */
  73. #include <ctype.h>
  74. #include <direct.h>
  75. #include "common.h"
  76. /* Local functions*/
  77. int IsDrive( char * input);
  78. int GetSearchNumber( char * input);
  79. int IsNetwareDrive (int driveNum);
  80. int IsLocalDrive (int driveNum);
  81. int IsNonNetwareNetworkDrive (int driveNum);
  82. int GetDriveFromSearchNumber (int searchNumber);
  83. void DisplayDriveMapping(WORD drive);
  84. void DisplaySearchDriveMapping(int searchNumber);
  85. int ParseMapPath(char * mapPath, char * volName, char * dirPath, char * serverName, int fMapErrorsOn, char *lpCommand);
  86. int MapDrive (int driveNum, int searchNum, char * mapPath, int bRoot, int bInsert, int fMapErrorsOn, char *lpCommand);
  87. int MapNonSearchDrive (int driveNum, char *mapPath, int bRoot, int fMapDisplayOn, int fMapErrorsOn, char *lpCommand);
  88. int MapSearchDrive (int searchNum, int driveNum, char *mapPath, int bInsert, int bRoot, int fMapDisplayOn, int fMapErrorsOn, char *lpCommand);
  89. int MapNextAvailableDrive (char *mapPath, int fMapDisplayOn, int fMapErrorsOn, char *lpCommand);
  90. void RemoveDriveFromPath(int searchNumber, int fMapErrorsOn);
  91. int RemoveDrive (WORD drive, int fMapDisplayOn, int fMapErrorsOn);
  92. void RemoveSearchDrive (int searchNumber, int fMapDisplayOn, int fMapErrorsOn);
  93. int InsertSearchDrive(int searchNum, int driveNum, int bInsert, char * insertPath);
  94. #define CM_MAP 0
  95. #define CM_DEL 1
  96. #define CM_NEXT 2
  97. #define CM_HELP 3
  98. #define MAX_INPUT_PATH_LEN 128
  99. int fMapDisplayOn = TRUE;
  100. int fMapErrorsOn = TRUE;
  101. int SafeDisk = 2;
  102. int GetFlag (char *buffer, int *pfInsert, int *pfRoot, char **ppPath)
  103. {
  104. int nFlag, nLen;
  105. char *lpSpace, *lpTemp;
  106. if (((*buffer == '/') || (*buffer == '-') || (*buffer == '\\')) &&
  107. (*(buffer+1) == '?'))
  108. return CM_HELP;
  109. lpSpace = strchr (buffer, ' ');
  110. nFlag = CM_MAP; // A bug!
  111. if (lpSpace == NULL)
  112. {
  113. *ppPath = buffer;
  114. return CM_MAP;
  115. }
  116. nLen = (int)(lpSpace - buffer);
  117. lpSpace++;
  118. if (!strncmp(buffer, __DEL__, max (3, nLen)) ||
  119. !strncmp(buffer, __REM__, max (3, nLen)))
  120. nFlag = CM_DEL;
  121. else if (!strncmp(buffer, __NEXT__, nLen))
  122. nFlag = CM_NEXT;
  123. else if (!strncmp(buffer, __INS__, max (3, nLen)))
  124. {
  125. *pfInsert = TRUE;
  126. if (lpTemp = strchr (lpSpace, ' '))
  127. {
  128. nLen = (int)(lpTemp - lpSpace);
  129. if (!strncmp(lpSpace, __ROOT__, nLen))
  130. {
  131. *pfRoot = TRUE;
  132. lpSpace = lpTemp+1;
  133. }
  134. }
  135. }
  136. else if (!strncmp(buffer, __ROOT__, nLen))
  137. {
  138. *pfRoot = TRUE;
  139. if (lpTemp = strchr (lpSpace, ' '))
  140. {
  141. nLen = (int)(lpTemp - lpSpace);
  142. if (!strncmp(lpSpace, __INS__, max (3, nLen)))
  143. {
  144. *pfInsert = TRUE;
  145. lpSpace = lpTemp+1;
  146. }
  147. }
  148. }
  149. else
  150. lpSpace = buffer;
  151. *ppPath = lpSpace;
  152. return(nFlag);
  153. }
  154. int Map (char * buffer)
  155. {
  156. WORD status, driveNum;
  157. char *lpCommand, *inputPath, *lpEqual;
  158. int fRoot, fInsert, fSpace, fCommandHandled;
  159. int nFlag, searchNumber, iRet;
  160. // Fix for NWCS.
  161. // NWGetDriveStatus() always returns 1800 on first call for non-Network
  162. // drives on NWCS. So we call with c: first to pass the first call.
  163. GetDriveStatus (3,
  164. NETWARE_FORMAT_SERVER_VOLUME,
  165. &status,
  166. NULL,
  167. NULL,
  168. NULL,
  169. NULL);
  170. lpCommand = strtok (buffer, ";");
  171. if (lpCommand == NULL)
  172. {
  173. DisplayMapping();
  174. return(0);
  175. }
  176. do
  177. {
  178. fRoot = FALSE;
  179. fInsert = FALSE;
  180. fSpace = FALSE;
  181. fCommandHandled = TRUE;
  182. // Make sure first and last char of the command are not spaces.
  183. if (*lpCommand == ' ')
  184. lpCommand++;
  185. if (*(lpCommand+strlen (lpCommand)-1) == ' ')
  186. *(lpCommand+strlen (lpCommand)-1) = 0;
  187. if (!strcmp (lpCommand, "DISPLAY ON"))
  188. {
  189. fMapDisplayOn = TRUE;
  190. continue;
  191. }
  192. else if (!strcmp (lpCommand, "DISPLAY OFF"))
  193. {
  194. fMapDisplayOn = FALSE;
  195. continue;
  196. }
  197. else if (!strcmp (lpCommand, "ERROR ON") || !strcmp (lpCommand, "ERRORS ON"))
  198. {
  199. fMapErrorsOn = TRUE;
  200. continue;
  201. }
  202. else if (!strcmp (lpCommand, "ERROR OFF") || !strcmp (lpCommand, "ERRORS OFF"))
  203. {
  204. fMapErrorsOn = FALSE;
  205. continue;
  206. }
  207. nFlag = GetFlag (lpCommand, &fInsert, &fRoot, &inputPath);
  208. /*
  209. * The 4X login program is much more forgiving about spaces
  210. * in the map command.
  211. */
  212. {
  213. char *lpTemp;
  214. char *lpCur;
  215. int inquote = FALSE;
  216. lpTemp = inputPath;
  217. lpCur = inputPath;
  218. /*
  219. * Compress blanks unless the string is quoted
  220. */
  221. while ( *lpTemp )
  222. {
  223. if ( *lpTemp == '\"' )
  224. {
  225. if ( inquote )
  226. inquote = FALSE;
  227. else
  228. inquote = TRUE;
  229. }
  230. else if ( !inquote &&
  231. (( *lpTemp == ' ' ) ||
  232. ( *lpTemp == '\t' ) ) )
  233. {
  234. }
  235. else
  236. {
  237. *lpCur++ = *lpTemp;
  238. if (IsDBCSLeadByte(*lpTemp)) {
  239. *lpCur++ = *(lpTemp+1);
  240. }
  241. }
  242. lpTemp = NWAnsiNext(lpTemp);
  243. }
  244. *lpCur = '\0';
  245. }
  246. if (nFlag == CM_HELP && fMapErrorsOn)
  247. DisplayMessage(IDR_MAP_USAGE);
  248. else if (nFlag == CM_NEXT)
  249. {
  250. if (strchr (inputPath, '=') ||
  251. strchr (inputPath, ' ') ||
  252. strchr (inputPath, '\t'))
  253. fCommandHandled = FALSE;
  254. else
  255. iRet = MapNextAvailableDrive (inputPath, fMapDisplayOn, fMapErrorsOn, lpCommand);
  256. }
  257. else if (nFlag == CM_DEL)
  258. {
  259. if (driveNum = (WORD) IsDrive (inputPath))
  260. iRet = RemoveDrive (driveNum, fMapDisplayOn, fMapErrorsOn);
  261. else if (searchNumber = GetSearchNumber(inputPath))
  262. RemoveSearchDrive (searchNumber, fMapDisplayOn, fMapErrorsOn);
  263. else
  264. fCommandHandled = FALSE;
  265. }
  266. else //nFlag = CM_MAP
  267. {
  268. if (driveNum = (WORD) IsDrive (inputPath))
  269. {
  270. if (fInsert)
  271. fCommandHandled = FALSE;
  272. else if (fRoot)
  273. iRet = MapNonSearchDrive (0, inputPath, TRUE, fMapDisplayOn, fMapErrorsOn, lpCommand);
  274. else
  275. DisplayDriveMapping(driveNum);
  276. }
  277. else if (searchNumber = GetSearchNumber (inputPath))
  278. {
  279. if (fInsert || fRoot)
  280. fCommandHandled = FALSE;
  281. else
  282. DisplaySearchDriveMapping(searchNumber);
  283. }
  284. else if ((lpEqual = strchr (inputPath, '=')) == NULL)
  285. {
  286. if (fInsert || strchr (inputPath, ' '))
  287. fCommandHandled = FALSE;
  288. else
  289. {
  290. /*
  291. * We must cope with MAP K:DIR which means change the
  292. * directory on K:
  293. */
  294. driveNum = 0;
  295. if (isalpha(inputPath[0]) && (inputPath[1] == ':'))
  296. {
  297. driveNum = toupper(inputPath[0]) - 'A' + 1;
  298. if ( !IsNetwareDrive(driveNum) )
  299. {
  300. driveNum = 0;
  301. }
  302. }
  303. iRet = MapNonSearchDrive (driveNum, inputPath, fRoot, fMapDisplayOn, fMapErrorsOn, lpCommand);
  304. }
  305. }
  306. else
  307. {
  308. if ( ( !fNDS && strchr (lpEqual+2, ' ') )
  309. || lpEqual == inputPath) {
  310. fCommandHandled = FALSE;
  311. }
  312. else
  313. {
  314. if (*AnsiPrev(inputPath, lpEqual) == ' ')
  315. {
  316. fSpace = TRUE;
  317. *(lpEqual-1) = 0;
  318. }
  319. else
  320. *lpEqual = 0;
  321. if (*(lpEqual+1) == ' ')
  322. lpEqual++;
  323. driveNum = (WORD) IsDrive (inputPath);
  324. searchNumber = GetSearchNumber (inputPath);
  325. *(inputPath+strlen(inputPath)) = fSpace? ' ' : '=';
  326. /*
  327. * This is to handle the cases:
  328. *
  329. * map x:=s3:=sys:public
  330. * map s3:=x:=sys:public
  331. *
  332. * Unfortuneatly the underlying parsing routines
  333. * want everything null terminated, so we need
  334. * to do the following shuffle.
  335. *
  336. */
  337. if ( driveNum || searchNumber )
  338. {
  339. if ((strchr (lpEqual+1, '=')) != NULL)
  340. {
  341. char * lpEqual2;
  342. char *tmpPath = _strdup( lpEqual+1 );
  343. lpEqual2 = strchr (tmpPath, '=');
  344. if (*AnsiPrev(tmpPath, lpEqual2) == ' ')
  345. {
  346. fSpace = TRUE;
  347. *(lpEqual2-1) = 0;
  348. }
  349. else
  350. *lpEqual2 = 0;
  351. if (*(lpEqual2+1) == ' ')
  352. lpEqual2++;
  353. if ( searchNumber )
  354. {
  355. driveNum = (WORD) IsDrive (tmpPath);
  356. }
  357. else
  358. {
  359. searchNumber = GetSearchNumber (tmpPath);
  360. }
  361. if ( driveNum && searchNumber )
  362. {
  363. lpEqual += (lpEqual2 - tmpPath) + 1;
  364. }
  365. free (tmpPath);
  366. }
  367. }
  368. if (searchNumber)
  369. {
  370. iRet = MapSearchDrive (searchNumber, driveNum, lpEqual+1, fInsert, fRoot, fMapDisplayOn, fMapErrorsOn, lpCommand);
  371. }
  372. else if (driveNum)
  373. {
  374. if (fInsert)
  375. fCommandHandled = FALSE;
  376. else
  377. iRet = MapNonSearchDrive (driveNum, lpEqual+1, fRoot, fMapDisplayOn, fMapErrorsOn, lpCommand);
  378. }
  379. else
  380. fCommandHandled = FALSE;
  381. }
  382. }
  383. }
  384. if (!fCommandHandled && fMapErrorsOn)
  385. {
  386. DisplayMessage(IDR_MAP_INVALID_PATH, lpCommand);
  387. }
  388. }while ((lpCommand = strtok (NULL, ";")) != NULL);
  389. return(iRet & 0xFF);
  390. }
  391. /* Return drive number if input is a drive specified as a letter followed
  392. by ':' for example if input is "A:", return 1
  393. or netware drive could be specified as *1: for example.
  394. Otherwise, return 0.
  395. */
  396. int IsDrive( char * input)
  397. {
  398. unsigned short driveNum = 0, n = 0;
  399. if (isalpha(input[0]) && (input[1] == ':') && (input[2] == 0))
  400. driveNum = toupper(input[0]) - 'A' + 1;
  401. else if (input[0] == '*' && isdigit (input[1]) && input[1] != '0')
  402. {
  403. if (isdigit (input[2]) && input[3] == ':' && input[4] == 0)
  404. n = (input[1]-'0')*10+(input[2]-'0');
  405. else if (input[2] == ':' && input[3] == 0)
  406. n = input[1]-'0';
  407. if (n)
  408. {
  409. GetFirstDrive (&driveNum);
  410. driveNum += (n-1);
  411. if (driveNum < 1 || driveNum > 26)
  412. driveNum = 0;
  413. }
  414. }
  415. return driveNum;
  416. }
  417. /*
  418. If the input is "Sn:", return n, where n > 0 && n <= 16.
  419. Otherwise return 0.
  420. */
  421. int GetSearchNumber( char * input)
  422. {
  423. int searchNumber = 0;
  424. char *lpTemp;
  425. if (input[0] != 'S')
  426. return(0);
  427. lpTemp = input+1;
  428. while (*lpTemp && isalpha(*lpTemp))
  429. lpTemp++;
  430. if (strncmp (input, "SEARCH", (UINT)(lpTemp-input)))
  431. return(0);
  432. if ((lpTemp[0] > '0') &&
  433. (lpTemp[0] <= '9'))
  434. {
  435. if ((lpTemp[1] == ':') &&
  436. (lpTemp[2] == 0))
  437. {
  438. searchNumber = lpTemp[0] - '0';
  439. }
  440. else if ((lpTemp[0] == '1') &&
  441. (lpTemp[1] >= '0') &&
  442. (lpTemp[1] <= '6') &&
  443. (lpTemp[2] == ':') &&
  444. (lpTemp[3] == 0))
  445. {
  446. searchNumber = 10 + lpTemp[1] - '0';
  447. }
  448. }
  449. return(searchNumber);
  450. }
  451. /*
  452. Return TRUE if the drive is a NetWare drive.
  453. FALSE otherwise.
  454. */
  455. int IsNetwareDrive (int driveNum)
  456. {
  457. unsigned int iRet=0;
  458. WORD status;
  459. if (iRet = GetDriveStatus ((unsigned short)driveNum,
  460. NETWARE_FORMAT_SERVER_VOLUME,
  461. &status,
  462. NULL,
  463. NULL,
  464. NULL,
  465. NULL))
  466. {
  467. return FALSE;
  468. }
  469. return (status & NETWARE_NETWARE_DRIVE);
  470. }
  471. /*
  472. Return TRUE if the drive is a local drive.
  473. FALSE otherwise.
  474. */
  475. int IsLocalDrive (int driveNum)
  476. {
  477. unsigned int iRet=0;
  478. WORD status;
  479. if (iRet = GetDriveStatus ((unsigned short)driveNum,
  480. NETWARE_FORMAT_SERVER_VOLUME,
  481. &status,
  482. NULL,
  483. NULL,
  484. NULL,
  485. NULL))
  486. {
  487. return FALSE;
  488. }
  489. return ((status & NETWARE_LOCAL_DRIVE) && !(status & NETWARE_NETWORK_DRIVE));
  490. }
  491. /*
  492. Return TRUE if the drive is a network drive that is not netware
  493. FALSE otherwise.
  494. */
  495. int IsNonNetwareNetworkDrive (int driveNum)
  496. {
  497. unsigned int iRet=0;
  498. WORD status;
  499. if (iRet = GetDriveStatus ((unsigned short)driveNum,
  500. NETWARE_FORMAT_SERVER_VOLUME,
  501. &status,
  502. NULL,
  503. NULL,
  504. NULL,
  505. NULL))
  506. {
  507. return FALSE;
  508. }
  509. return ((status & NETWARE_NETWORK_DRIVE) && !(status & NETWARE_NETWARE_DRIVE));
  510. }
  511. /*
  512. Return the drive number of search drive n.
  513. Return 0 if search drive n does not exist.
  514. */
  515. int GetDriveFromSearchNumber (int searchNumber)
  516. {
  517. char *path;
  518. int i;
  519. path = getenv("PATH");
  520. if (path == NULL) {
  521. return 0;
  522. }
  523. for (i = 1; i < searchNumber; i++)
  524. {
  525. path =strchr (path, ';');
  526. if (path == NULL || *(path+1) == 0)
  527. return(0);
  528. path++;
  529. }
  530. return(toupper(*path) - 'A' + 1);
  531. }
  532. /*
  533. Display a specific drive's mapping.
  534. */
  535. void DisplayDriveMapping(WORD drive)
  536. {
  537. unsigned int iRet = 0;
  538. WORD status = 0;
  539. char rootPath[MAX_PATH_LEN], relativePath[MAX_PATH_LEN];
  540. iRet = GetDriveStatus (drive,
  541. NETWARE_FORMAT_SERVER_VOLUME,
  542. &status,
  543. NULL,
  544. rootPath,
  545. relativePath,
  546. NULL);
  547. if (iRet)
  548. {
  549. DisplayError (iRet, "GetDriveStatus");
  550. return;
  551. }
  552. if (status & NETWARE_NETWARE_DRIVE)
  553. DisplayMessage(IDR_NETWARE_DRIVE, 'A'+drive-1, rootPath, relativePath);
  554. else if ((status & NETWARE_NETWORK_DRIVE) || (status & NETWARE_LOCAL_DRIVE))
  555. DisplayMessage(IDR_LOCAL_DRIVE, 'A'+drive-1);
  556. else
  557. DisplayMessage(IDR_UNDEFINED, 'A'+drive-1);
  558. }
  559. /*
  560. Display a specific search drive's mapping.
  561. */
  562. void DisplaySearchDriveMapping(int searchNumber)
  563. {
  564. unsigned int iRet = 0;
  565. char *p, *searchPath;
  566. int i;
  567. WORD status;
  568. char path[MAX_PATH_LEN], rootPath[MAX_PATH_LEN], relativePath[MAX_PATH_LEN];
  569. searchPath = NWGetPath();
  570. if (searchPath == NULL) {
  571. return;
  572. }
  573. for (i = 0; i < searchNumber-1; i++)
  574. {
  575. searchPath = strchr (searchPath, ';');
  576. if (searchPath != NULL)
  577. searchPath++;
  578. else
  579. return;
  580. }
  581. p = strchr (searchPath, ';');
  582. if (p != NULL)
  583. {
  584. i= (int)(p-searchPath);
  585. strncpy (path, searchPath, i);
  586. path[i] = 0;
  587. }
  588. else
  589. strcpy (path, searchPath);
  590. if (isalpha(*path) && *(path+1) == ':')
  591. {
  592. iRet = GetDriveStatus ((unsigned short)(toupper(*path)-'A'+1),
  593. NETWARE_FORMAT_SERVER_VOLUME,
  594. &status,
  595. NULL,
  596. rootPath,
  597. relativePath,
  598. NULL);
  599. if (iRet)
  600. {
  601. DisplayError (iRet, "GetDriveStatus");
  602. return;
  603. }
  604. else
  605. {
  606. if (status & NETWARE_NETWARE_DRIVE)
  607. DisplayMessage(IDR_NETWARE_SEARCH, searchNumber, path, rootPath, relativePath);
  608. else
  609. DisplayMessage(IDR_LOCAL_SEARCH, searchNumber, path);
  610. }
  611. }
  612. else
  613. DisplayMessage(IDR_LOCAL_SEARCH, searchNumber, path);
  614. }
  615. /*
  616. Return TRUE if the mapPath is parsed, FALSE otherwise.
  617. */
  618. int ParseMapPath(char * mapPath, char * volName, char * dirPath, char * serverName, int fMapErrorsOn, char * lpCommand)
  619. {
  620. unsigned int iRet=0;
  621. char *pColon, inputPath[MAX_PATH_LEN];
  622. int drive, nDriveNum;
  623. // fix g:=:sys:\public case.
  624. if (*mapPath == ':')
  625. mapPath++;
  626. if (strlen (mapPath) > MAX_INPUT_PATH_LEN)
  627. {
  628. if (fMapErrorsOn)
  629. DisplayMessage(IDR_INVALID_PATH, mapPath);
  630. return FALSE;
  631. }
  632. // Get the drive or volume part if there is one.
  633. if (pColon = strchr (mapPath, ':'))
  634. {
  635. char *directory = pColon+1;
  636. int searchNumber;
  637. // Assing drive: part to input.
  638. strncpy (inputPath, mapPath, (UINT)(directory-mapPath));
  639. inputPath[directory-mapPath] = 0;
  640. if (nDriveNum = IsDrive (inputPath))
  641. {
  642. if (*inputPath == '*')
  643. {
  644. *inputPath = 'A' + nDriveNum - 1;
  645. *(inputPath+1) = ':';
  646. *(inputPath+2) = 0;
  647. }
  648. else if (!IsNetwareDrive(nDriveNum))
  649. {
  650. if (fMapErrorsOn)
  651. DisplayMessage(IDR_NOT_NETWORK_DRIVE);
  652. return(FALSE);
  653. }
  654. }
  655. else if (searchNumber = GetSearchNumber(inputPath))
  656. {
  657. int drive = GetDriveFromSearchNumber (searchNumber);
  658. if (!drive)
  659. {
  660. if (fMapErrorsOn)
  661. DisplayMessage(IDR_SEARCH_DRIVE_NOT_EXIST, searchNumber);
  662. return FALSE;
  663. }
  664. if (!IsNetwareDrive(drive))
  665. {
  666. if (fMapErrorsOn)
  667. DisplayMessage(IDR_NOT_NETWORK_DRIVE);
  668. return(FALSE);
  669. }
  670. inputPath[0] = 'A' + drive - 1;
  671. inputPath[1] = ':';
  672. inputPath[2] = 0;
  673. }
  674. strcat (inputPath, directory);
  675. }
  676. else
  677. {
  678. if ( fNDS )
  679. {
  680. CHAR fullname[MAX_PATH];
  681. if ( !NDSCanonicalizeName( mapPath, fullname, MAX_PATH, TRUE ) )
  682. if ( !ConverNDSPathToNetWarePathA( fullname, DSCL_DIRECTORY_MAP,
  683. inputPath ) )
  684. goto ParseThePath;
  685. }
  686. // If drive is not specified, the current drive is used.
  687. drive = _getdrive();
  688. if (!IsNetwareDrive(drive))
  689. {
  690. if (fMapErrorsOn)
  691. DisplayMessage(IDR_NOT_NETWORK_DRIVE);
  692. return(FALSE);
  693. }
  694. inputPath[0] = 'A'+drive-1;
  695. inputPath[1] = ':';
  696. inputPath[2] = 0;
  697. strcat (inputPath, mapPath);
  698. }
  699. ParseThePath:
  700. iRet = ParsePath (inputPath,
  701. serverName,
  702. volName,
  703. dirPath);
  704. if (iRet)
  705. {
  706. if (iRet == 0x880F)
  707. {
  708. DisplayMessage(IDR_MAP_NOT_ATTACHED_SERVER, lpCommand);
  709. return(FALSE);
  710. }
  711. else
  712. {
  713. if (fMapErrorsOn)
  714. DisplayMessage(IDR_INVALID_PATH, inputPath);
  715. return(FALSE);
  716. }
  717. }
  718. return(TRUE);
  719. }
  720. /*
  721. Map drive to mapPath
  722. */
  723. int MapDrive (int drive, int searchNum, char * mapPath, int bRoot, int bInsert, int fMapErrorsOn, char *lpCommand)
  724. {
  725. unsigned int iRet=0;
  726. char volName[MAX_VOLUME_LEN+1]; //+1 for append ':'.
  727. char dirPath[MAX_DIR_PATH_LEN];
  728. int currentDrive;
  729. int OvermapDrive = -1;
  730. char serverName[MAX_NAME_LEN];
  731. if (!ParseMapPath(mapPath, volName, dirPath, serverName, fMapErrorsOn, lpCommand))
  732. return(3);
  733. if (IsNetwareDrive(drive))
  734. {
  735. if ( drive == _getdrive() ) {
  736. OvermapDrive = drive;
  737. _chdrive (SafeDisk);
  738. }
  739. if (iRet = DeleteDriveBase ((unsigned short)drive))
  740. {
  741. if (fMapErrorsOn) {
  742. /* Cannot delete the drive you are on */
  743. if (iRet == ERROR_DEVICE_IN_USE)
  744. DisplayMessage(IDR_CAN_NOT_CHANGE_DRIVE);
  745. else
  746. DisplayError (iRet, "DeleteDriveBase");
  747. }
  748. return iRet;
  749. }
  750. }
  751. else if ( IsNonNetwareNetworkDrive(drive) ) {
  752. if (fMapErrorsOn)
  753. DisplayMessage(IDR_NON_NETWARE_NETWORK_DRIVE, lpCommand);
  754. return 3;
  755. }
  756. if (bRoot)
  757. {
  758. // +2 is for strcat with ":".
  759. char *fullPath = malloc( MAX_VOLUME_LEN + strlen (dirPath) + 2);
  760. if (fullPath == NULL)
  761. {
  762. if (fMapErrorsOn)
  763. DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
  764. return 8;
  765. }
  766. strcpy (fullPath, volName);
  767. strcat (fullPath, ":");
  768. strcat (fullPath, dirPath);
  769. iRet = SetDriveBase ((unsigned short)drive,
  770. serverName,
  771. 0,
  772. fullPath);
  773. // Relative names need to be expanded for the redirector
  774. if ( iRet && fNDS && ( volName[strlen(volName) - 1] == '.' ) )
  775. {
  776. char canonName[MAX_VOLUME_LEN+1];
  777. if ( !NDSCanonicalizeName( volName, canonName, MAX_VOLUME_LEN, TRUE ) )
  778. {
  779. strcpy (fullPath, canonName);
  780. strcat (fullPath, ":");
  781. strcat (fullPath, dirPath);
  782. iRet = SetDriveBase ((unsigned short)drive,
  783. serverName,
  784. 0,
  785. fullPath);
  786. }
  787. }
  788. if (iRet == 0)
  789. {
  790. if (searchNum)
  791. searchNum = InsertSearchDrive(searchNum, drive, bInsert, NULL);
  792. currentDrive = _getdrive();
  793. _chdrive (drive);
  794. _chdir( "\\" );
  795. _chdrive (currentDrive);
  796. ExportCurrentDirectory( drive );
  797. if (fMapDisplayOn)
  798. {
  799. if (searchNum)
  800. DisplaySearchDriveMapping (searchNum);
  801. else
  802. DisplayDriveMapping((unsigned short)drive);
  803. }
  804. }
  805. else
  806. {
  807. if (fMapErrorsOn)
  808. {
  809. switch ( iRet )
  810. {
  811. case ERROR_DEVICE_IN_USE:
  812. DisplayMessage(IDR_CAN_NOT_CHANGE_DRIVE);
  813. break;
  814. case ERROR_BAD_NETPATH:
  815. case ERROR_BAD_NET_NAME:
  816. DisplayMessage(IDR_VOLUME_NOT_EXIST, volName);
  817. iRet = 3;
  818. break;
  819. case ERROR_EXTENDED_ERROR:
  820. NTPrintExtendedError();
  821. iRet = 3;
  822. break;
  823. default:
  824. DisplayMessage(IDR_MAP_ERROR, iRet);
  825. DisplayMessage(IDR_MAP_FAILED, lpCommand);
  826. iRet = 3;
  827. break;
  828. }
  829. }
  830. }
  831. free (fullPath);
  832. }
  833. else
  834. {
  835. // NETX requires to end the volName with ':'.
  836. strcat (volName, ":");
  837. iRet = SetDriveBase ((unsigned short)drive,
  838. serverName,
  839. 0,
  840. volName);
  841. // Relative names need to be expanded for the redirector
  842. if ( iRet && fNDS && ( volName[strlen(volName) - 2] == '.' ) )
  843. {
  844. char canonName[MAX_VOLUME_LEN+1];
  845. volName[strlen(volName)-1] = '\0';
  846. if ( !NDSCanonicalizeName( volName, canonName, MAX_VOLUME_LEN, TRUE ) )
  847. {
  848. strcat (canonName, ":");
  849. iRet = SetDriveBase ((unsigned short)drive,
  850. serverName,
  851. 0,
  852. canonName);
  853. }
  854. }
  855. if (iRet)
  856. {
  857. if (fMapErrorsOn)
  858. {
  859. switch ( iRet )
  860. {
  861. case ERROR_DEVICE_IN_USE:
  862. DisplayMessage(IDR_CAN_NOT_CHANGE_DRIVE);
  863. break;
  864. case ERROR_EXTENDED_ERROR:
  865. NTPrintExtendedError();
  866. iRet = 3;
  867. break;
  868. case ERROR_BAD_NETPATH:
  869. case ERROR_BAD_NET_NAME:
  870. default:
  871. DisplayMessage(IDR_MAP_INVALID_PATH, lpCommand);
  872. iRet = 3;
  873. break;
  874. }
  875. }
  876. }
  877. else
  878. {
  879. // Succeed.
  880. if (searchNum)
  881. searchNum = InsertSearchDrive(searchNum, drive, bInsert, NULL);
  882. currentDrive = _getdrive();
  883. _chdrive (drive);
  884. if (!iRet && *dirPath)
  885. {
  886. iRet = _chdir( "\\" );
  887. if ( !iRet )
  888. iRet = _chdir (dirPath);
  889. if ( iRet ) {
  890. if (fMapErrorsOn)
  891. {
  892. DisplayMessage(IDR_MAP_INVALID_PATH, lpCommand);
  893. }
  894. iRet = 3;
  895. }
  896. }
  897. else
  898. {
  899. _chdir( "\\" );
  900. }
  901. _chdrive (currentDrive);
  902. ExportCurrentDirectory( drive );
  903. if (iRet == 0 && fMapDisplayOn)
  904. {
  905. if (searchNum)
  906. DisplaySearchDriveMapping (searchNum);
  907. else
  908. DisplayDriveMapping((unsigned short)drive);
  909. }
  910. }
  911. }
  912. if ( OvermapDrive != -1 )
  913. _chdrive (OvermapDrive);
  914. return(iRet);
  915. }
  916. /*
  917. Map drive secified by driveNum to mapPath.
  918. If bRoot is TRUE, use mapPath as the drive base.
  919. */
  920. int MapNonSearchDrive (int driveNum, char *mapPath, int bRoot, int fMapDisplayOn, int fMapErrorsOn, char *lpCommand)
  921. {
  922. int driveLetter, iRet = 0;
  923. if ((driveNum == 0) && (!strchr(mapPath, ':') && !bRoot))
  924. {
  925. // map current drive to different directory.
  926. if (_chdir(mapPath) && fMapErrorsOn)
  927. {
  928. DisplayMessage(IDR_DIRECTORY_NOT_FOUND, mapPath);
  929. iRet = 3;
  930. }
  931. else {
  932. ExportCurrentDirectory( _getdrive() );
  933. if (fMapDisplayOn)
  934. DisplayDriveMapping((unsigned short)driveNum);
  935. }
  936. return(iRet);
  937. }
  938. else if ( (driveNum) && (isalpha(mapPath[0]) && (mapPath[1] == ':')))
  939. {
  940. int mapdriveNum = toupper(mapPath[0]) - 'A' + 1;
  941. if ( driveNum == mapdriveNum )
  942. {
  943. // map drive to different directory.
  944. // map k:=k:\dir
  945. WORD currentDrive;
  946. currentDrive = (USHORT) _getdrive();
  947. _chdrive (driveNum);
  948. if (_chdir(mapPath) && fMapErrorsOn)
  949. {
  950. DisplayMessage(IDR_DIRECTORY_NOT_FOUND, mapPath);
  951. iRet = 3;
  952. }
  953. else
  954. {
  955. ExportCurrentDirectory( _getdrive() );
  956. if (fMapDisplayOn)
  957. DisplayDriveMapping((unsigned short)driveNum);
  958. }
  959. _chdrive (currentDrive);
  960. return(iRet);
  961. }
  962. }
  963. if (driveNum == 0)
  964. driveNum = _getdrive();
  965. driveLetter = 'A' + driveNum -1;
  966. return MapDrive (driveNum, 0, mapPath, bRoot, 0, fMapErrorsOn, lpCommand);
  967. }
  968. /*
  969. Map the last free drive to mapPath and put it in the search path.
  970. If bInsert is TRUE, don't replace search drive n, otherwise,
  971. replace.
  972. If bRoot is TRUE, use mapPath as the drive base.
  973. */
  974. int MapSearchDrive (int searchNum, int driveNum, char *mapPath, int bInsert, int bRoot, int fMapDisplayOn, int fMapErrorsOn, char *lpCommand)
  975. {
  976. unsigned int iRet=0;
  977. int i;
  978. WORD status;
  979. char * lpEqual;
  980. /*
  981. * Handle syntax map s2:=w:=volume:
  982. * Handle syntax map w:=s2:=volume:
  983. */
  984. if ( driveNum )
  985. {
  986. return MapDrive (driveNum, searchNum, mapPath, bRoot, bInsert, fMapErrorsOn, lpCommand);
  987. }
  988. // Check if mapPath is local path.
  989. if (mapPath[1] == ':' &&
  990. IsLocalDrive (toupper(mapPath[0])-'A'+1))
  991. {
  992. i = 0; // a bug?
  993. searchNum = InsertSearchDrive(searchNum, i, bInsert, mapPath);
  994. if ((searchNum != 0) && fMapDisplayOn)
  995. DisplayMessage(IDR_LOCAL_SEARCH, searchNum, mapPath);
  996. return 0;
  997. }
  998. // Try to find the last available drive.
  999. for (i = 26; i >= 1; i--)
  1000. {
  1001. iRet = GetDriveStatus ((unsigned short)i,
  1002. NETWARE_FORMAT_SERVER_VOLUME,
  1003. &status,
  1004. NULL,
  1005. NULL,
  1006. NULL,
  1007. NULL);
  1008. if (iRet)
  1009. continue;
  1010. if (!(status & NETWARE_LOCAL_DRIVE) &&
  1011. !(status & NETWARE_NETWORK_DRIVE))
  1012. {
  1013. // Found. Map it to the path.
  1014. return MapDrive (i, searchNum, mapPath, bRoot, bInsert, fMapErrorsOn, lpCommand);
  1015. }
  1016. }
  1017. if (fMapErrorsOn)
  1018. DisplayMessage (IDR_NO_DRIVE_AVAIL);
  1019. return(0);
  1020. }
  1021. /*
  1022. Map the next available drive to the mapPath.
  1023. */
  1024. int MapNextAvailableDrive (char *mapPath, int fMapDisplayOn, int fMapErrorsOn, char *lpCommand)
  1025. {
  1026. unsigned int iRet = 0;
  1027. int i;
  1028. WORD status;
  1029. // Find a free drive that is not mapped.
  1030. // Then map it to the mapPath.
  1031. for (i = 1; i <= 26; i++)
  1032. {
  1033. iRet = GetDriveStatus ((unsigned short)i,
  1034. NETWARE_FORMAT_SERVER_VOLUME,
  1035. &status,
  1036. NULL,
  1037. NULL,
  1038. NULL,
  1039. NULL);
  1040. if (iRet)
  1041. {
  1042. if (fMapErrorsOn)
  1043. DisplayError (iRet, "GetDriveStatus");
  1044. return iRet;
  1045. }
  1046. if (!(status & NETWARE_LOCAL_DRIVE) &&
  1047. !(status & NETWARE_NETWORK_DRIVE))
  1048. {
  1049. iRet = MapNonSearchDrive (i, mapPath, FALSE, fMapDisplayOn, fMapErrorsOn, lpCommand);
  1050. return iRet;
  1051. }
  1052. }
  1053. if (fMapErrorsOn)
  1054. DisplayMessage(IDR_NO_DRIVE_AVAIL);
  1055. return(0);
  1056. }
  1057. /*
  1058. Remove a drive mapping.
  1059. */
  1060. int RemoveDrive (WORD drive, int fMapDisplayOn, int fMapErrorsOn)
  1061. {
  1062. unsigned int iRet=0;
  1063. int searchNum;
  1064. if (IsNetwareDrive (drive))
  1065. {
  1066. if (searchNum = IsSearchDrive(drive))
  1067. {
  1068. RemoveSearchDrive (searchNum, fMapDisplayOn, fMapErrorsOn);
  1069. }
  1070. else
  1071. {
  1072. /*
  1073. * Can't delete current drive on NT
  1074. */
  1075. if ( drive == _getdrive() ) {
  1076. _chdrive (SafeDisk);
  1077. }
  1078. if (iRet = DeleteDriveBase (drive))
  1079. {
  1080. if (fMapErrorsOn)
  1081. DisplayError (iRet, "DeleteDriveBase");
  1082. }
  1083. else
  1084. {
  1085. if (fMapDisplayOn)
  1086. DisplayMessage(IDR_DEL_DRIVE, 'A'+drive-1);
  1087. }
  1088. }
  1089. }
  1090. else
  1091. {
  1092. if (fMapErrorsOn)
  1093. DisplayMessage(IDR_WRONG_DRIVE, 'A'+drive-1);
  1094. return(50); //error level.
  1095. }
  1096. return(0);
  1097. }
  1098. /*
  1099. Remove a search drive.
  1100. */
  1101. void RemoveSearchDrive (int searchNumber, int fMapDisplayOn, int fMapErrorsOn)
  1102. {
  1103. WORD drive;
  1104. // Get the drive number.
  1105. drive = (WORD) GetDriveFromSearchNumber (searchNumber);
  1106. if (!drive)
  1107. {
  1108. if (fMapErrorsOn)
  1109. DisplayMessage(IDR_SEARCH_DRIVE_NOT_EXIST, searchNumber);
  1110. return;
  1111. }
  1112. // If the drive is a netware drive, remove the drive mapping.
  1113. if (IsNetwareDrive (drive))
  1114. {
  1115. unsigned int iRet=0;
  1116. /*
  1117. * Can't delete current drive on NT
  1118. */
  1119. if ( drive == _getdrive() ) {
  1120. _chdrive (SafeDisk);
  1121. }
  1122. if (iRet = DeleteDriveBase (drive))
  1123. {
  1124. if (fMapErrorsOn)
  1125. DisplayError (iRet, "DeleteDriveBase");
  1126. return;
  1127. }
  1128. }
  1129. RemoveDriveFromPath (searchNumber, fMapErrorsOn);
  1130. if (fMapDisplayOn)
  1131. DisplayMessage(IDR_DEL_SEARCH_DRIVE, 'A'+drive-1);
  1132. // If the drive is not a local drive, remove all reference
  1133. // to the drive in the path.
  1134. if (!IsLocalDrive (drive))
  1135. {
  1136. while (searchNumber = IsSearchDrive (drive))
  1137. {
  1138. RemoveDriveFromPath (searchNumber, fMapErrorsOn);
  1139. }
  1140. }
  1141. }
  1142. /*
  1143. Remove a search drive from the path.
  1144. */
  1145. void RemoveDriveFromPath(int searchNumber, int fMapErrorsOn)
  1146. {
  1147. char *pOldPath, *pNewPath, *restEnvSeg, *pPath, *Path;
  1148. int i, n;
  1149. // Move pOldPath to where we want to put the new path string.
  1150. pOldPath = NWGetPath();
  1151. if (pOldPath == NULL) {
  1152. return;
  1153. }
  1154. pPath = malloc( strlen(pOldPath) + 5 + 1 + 1 );
  1155. if (pPath == NULL) {
  1156. return;
  1157. }
  1158. strcpy(pPath, "PATH=");
  1159. strcat(pPath, pOldPath);
  1160. pOldPath = pPath + 5;
  1161. for (i = 1; i < searchNumber; i++)
  1162. {
  1163. pOldPath=strchr (pOldPath, ';');
  1164. if (pOldPath == NULL)
  1165. {
  1166. if (fMapErrorsOn)
  1167. DisplayMessage(IDR_SEARCH_DRIVE_NOT_EXIST, searchNumber);
  1168. free( pPath );
  1169. return;
  1170. }
  1171. pOldPath++;
  1172. }
  1173. // Move pNewPath to the beginning of the path string that
  1174. // needs to be moved.
  1175. if (pNewPath = strchr (pOldPath, ';'))
  1176. pNewPath++ ;
  1177. else
  1178. pNewPath = pOldPath + strlen (pOldPath);
  1179. // Calculate the number of characters needs to be moved.
  1180. n = strlen (pNewPath) + 1;
  1181. restEnvSeg = pNewPath + n;
  1182. n++;
  1183. // Move the path string to overwrite the search drive.
  1184. memmove (pOldPath, pNewPath, n);
  1185. Path = malloc (strlen (pPath)+1);
  1186. if (Path) {
  1187. strcpy (Path, pPath);
  1188. _putenv (Path);
  1189. }
  1190. ExportEnv( pPath );
  1191. free( pPath );
  1192. }
  1193. /*
  1194. If bInsert is TRUE, insert dirve specified by driveNum as search
  1195. drive specified by searchNum. Otherwise replace search drive
  1196. specified by searchNum with drive specified by driveNum.
  1197. */
  1198. int InsertSearchDrive(int searchNum, int driveNum, int bInsert, char * insertPath)
  1199. {
  1200. char *pOldPath, *pNewPath, *restEnvSeg, *pPath, *Path;
  1201. int i, n = 0, bSemiColon, nInsertChar;
  1202. nInsertChar = (insertPath == NULL)? 3 : strlen (insertPath);
  1203. // Check if memory block is large enough.
  1204. if (!MemorySegmentLargeEnough (nInsertChar+1))
  1205. return 0;
  1206. // Move pNewPath to where we put the new drive.
  1207. pNewPath = NWGetPath();
  1208. //-- Multi user code merge. Citrix bug fixes ----
  1209. // 8/14/96 cjc Fix trap cause path is NULL.
  1210. pPath = NULL; //compiler error
  1211. if (!pNewPath) {
  1212. pPath = malloc( 5 + 1 + nInsertChar + 1 + 1 );
  1213. }
  1214. else {
  1215. pPath = malloc( strlen(pNewPath) + 5 + 1 + nInsertChar + 1 + 1 );
  1216. }
  1217. if (pPath == NULL) {
  1218. return 0;
  1219. }
  1220. strcpy(pPath, "PATH=");
  1221. if (pNewPath) {
  1222. strcat(pPath, pNewPath);
  1223. }
  1224. pNewPath = pPath + 5;
  1225. for (i = 1; i < searchNum; i++)
  1226. {
  1227. if (strchr (pNewPath, ';'))
  1228. {
  1229. pNewPath = strchr (pNewPath, ';');
  1230. }
  1231. else
  1232. {
  1233. pNewPath += strlen (pNewPath);
  1234. bInsert = TRUE;
  1235. i++;
  1236. break;
  1237. }
  1238. pNewPath++;
  1239. }
  1240. // Move pOldPath to the begining of the path string that needs
  1241. // to be moved.
  1242. if (bInsert)
  1243. pOldPath = pNewPath;
  1244. else
  1245. {
  1246. if ((pOldPath = strchr (pNewPath, ';')) == NULL)
  1247. pOldPath = pNewPath + strlen (pNewPath);
  1248. else
  1249. pOldPath++;
  1250. }
  1251. // Figure out the number of characters that need to be moved.
  1252. n = strlen (pOldPath) + 1;
  1253. restEnvSeg = pOldPath + strlen (pOldPath) + 1;
  1254. n++;
  1255. // If we insert a new drive to the end of the path which ends with
  1256. // a ';', or if we replace the last search drive, no ';' is needed.
  1257. bSemiColon = bInsert ? (*(pNewPath-1) != ';' || *pOldPath != 0)
  1258. : (*pOldPath != 0);
  1259. // Move the old path so that we will have space for the new search drive.
  1260. memmove (pNewPath + (bSemiColon? nInsertChar+1:nInsertChar), pOldPath, n);
  1261. if ((*pNewPath == 0)&& bSemiColon)
  1262. {
  1263. // Insert as the last one to the path.
  1264. // Put ';' at the begining.
  1265. *pNewPath = ';';
  1266. if (insertPath == NULL)
  1267. {
  1268. *(pNewPath+1) = 'A' + driveNum - 1;
  1269. *(pNewPath+2) = ':';
  1270. *(pNewPath+3) = '.';
  1271. }
  1272. else
  1273. memcpy (pNewPath+1, insertPath, nInsertChar);
  1274. }
  1275. else
  1276. {
  1277. if (insertPath == NULL)
  1278. {
  1279. *pNewPath = 'A' + driveNum - 1;
  1280. *(pNewPath+1) = ':';
  1281. *(pNewPath+2) = '.';
  1282. }
  1283. else
  1284. memcpy (pNewPath, insertPath, nInsertChar);
  1285. if (bSemiColon)
  1286. *(pNewPath+nInsertChar) = ';';
  1287. }
  1288. Path = malloc (strlen (pPath)+1);
  1289. if (Path) {
  1290. strcpy (Path, pPath);
  1291. _putenv (Path);
  1292. }
  1293. ExportEnv( pPath );
  1294. free( pPath );
  1295. return (i);
  1296. }
  1297. /*
  1298. * Used by SetEnv().
  1299. * Return the number of bytes of environment variable pointed by lpRest
  1300. */
  1301. int GetRestEnvLen (char *lpRest)
  1302. {
  1303. int nTotal = 1;
  1304. nTotal += strlen (lpRest);
  1305. return(nTotal);
  1306. }