Windows NT 4.0 source code leak
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.

1379 lines
34 KiB

4 years ago
  1. /****************************************************************************/
  2. /* */
  3. /* WFUTIL.C - */
  4. /* */
  5. /* Windows File System String Utility Functions */
  6. /* */
  7. /****************************************************************************/
  8. #include "winfile.h"
  9. #include "lfn.h"
  10. #include "winnet.h"
  11. #include "wnetcaps.h" // WNetGetCaps()
  12. #include "stdlib.h"
  13. int rgiDriveType[26];
  14. PSTR CurDirCache[26];
  15. // cache GetDriveType calls for speed
  16. INT NEAR PASCAL DriveType(INT iDrive)
  17. {
  18. if (rgiDriveType[iDrive] != -1)
  19. return rgiDriveType[iDrive];
  20. return rgiDriveType[iDrive] = MGetDriveType(iDrive);
  21. }
  22. VOID NEAR PASCAL InvalidateDriveType()
  23. {
  24. INT i;
  25. for (i = 0; i < 26; i++)
  26. rgiDriveType[i] = -1;
  27. }
  28. // iDrive zero based drive number (0 = A, 1 = B)
  29. // returns:
  30. // TRUE we have it saved pszPath gets path
  31. // FALSE we don't have it saved
  32. BOOL APIENTRY GetSavedDirectory(INT iDrive, PSTR pszPath)
  33. {
  34. if (CurDirCache[iDrive]) {
  35. lstrcpy(pszPath, CurDirCache[iDrive]);
  36. return TRUE;
  37. } else
  38. return FALSE;
  39. }
  40. VOID APIENTRY SaveDirectory(PSTR pszPath)
  41. {
  42. INT i;
  43. i = DRIVEID(pszPath);
  44. if (CurDirCache[i])
  45. LocalFree((HANDLE)CurDirCache[i]);
  46. CurDirCache[i] = (PSTR)LocalAlloc(LPTR, lstrlen(pszPath)+1);
  47. if (CurDirCache[i])
  48. lstrcpy(CurDirCache[i], pszPath);
  49. }
  50. /*
  51. * GetSelectedDrive() -
  52. *
  53. * Get the selected drive from the currently active window
  54. *
  55. * should be in wfutil.c
  56. */
  57. INT APIENTRY GetSelectedDrive()
  58. {
  59. HWND hwnd;
  60. hwnd = (HWND)SendMessage(hwndMDIClient,WM_MDIGETACTIVE,0,0L);
  61. return (INT)SendMessage(hwnd,FS_GETDRIVE,0,0L) - (INT)'A';
  62. }
  63. /*
  64. * GetSelectedDirectory() -
  65. *
  66. * Gets the directory selected for the drive. uses the windows
  67. * z-order to give precidence to windows higher in the order.
  68. *
  69. * works like GetCurrentDirectory() except it looks through
  70. * the window list for directories first (and returns ANSI)
  71. *
  72. * returns:
  73. * lpDir ANSI string of current dir
  74. */
  75. VOID APIENTRY GetSelectedDirectory(WORD iDrive, PSTR pszDir)
  76. {
  77. HWND hwnd;
  78. WORD iDriveT;
  79. if (iDrive) {
  80. for (hwnd = GetWindow(hwndMDIClient,GW_CHILD);
  81. hwnd;
  82. hwnd = GetWindow(hwnd,GW_HWNDNEXT)) {
  83. iDriveT = (WORD)SendMessage(hwnd,FS_GETDRIVE,0,0L);
  84. if (iDrive == (WORD)(iDriveT - 'A' + 1))
  85. goto hwndfound;
  86. }
  87. if (!GetSavedDirectory(iDrive - 1, pszDir)) {
  88. SheGetDir(iDrive,pszDir);
  89. OemToAnsi(pszDir,pszDir);
  90. }
  91. return;
  92. } else
  93. hwnd = (HWND)SendMessage(hwndMDIClient,WM_MDIGETACTIVE,0,0L);
  94. hwndfound:
  95. SendMessage(hwnd,FS_GETDIRECTORY,MAXPATHLEN,(LONG)(LPSTR)pszDir);
  96. StripBackslash(pszDir);
  97. }
  98. // avoid confusion in DOSs upper case mapping by converting to
  99. // upper case before passing down to dos
  100. VOID APIENTRY FixAnsiPathForDos(LPSTR szPath)
  101. {
  102. #ifdef LFN
  103. if (GetNameType(szPath) == FILE_83_CI)
  104. #endif
  105. AnsiUpper(szPath);
  106. AnsiToOem(szPath, szPath);
  107. }
  108. // refresh a MDI child window (works for any type of mdi child)
  109. VOID APIENTRY RefreshWindow(HWND hwndActive)
  110. {
  111. HWND hwndTree, hwndDir;
  112. DWORD lParam;
  113. CHAR szDir[MAXPATHLEN];
  114. INT iDrive;
  115. cDrives = UpdateDriveList(); // updates rgiDrive[]
  116. InitDriveBitmaps();
  117. // make sure the thing is still there (floppy drive, net drive)
  118. iDrive = (INT)GetWindowLong(hwndActive, GWL_TYPE);
  119. if ((iDrive >= 0) && !CheckDrive(hwndActive, iDrive))
  120. return;
  121. // update the dir part first so tree can steal later
  122. if (hwndDir = HasDirWindow(hwndActive))
  123. SendMessage(hwndDir, FS_CHANGEDISPLAY, CD_PATH, 0L);
  124. if (hwndTree = HasTreeWindow(hwndActive)) {
  125. // remember the current directory
  126. SendMessage(hwndActive, FS_GETDIRECTORY, sizeof(szDir), (LONG)(LPSTR)szDir);
  127. // update the drives windows
  128. SendMessage(hwndActive, FS_CHANGEDRIVES, 0, 0L);
  129. if (IsValidDisk(szDir[0] - 'A'))
  130. lParam = (LONG)szDir;
  131. else
  132. lParam = 0;
  133. // update the tree
  134. SendMessage(hwndTree, TC_SETDRIVE, MAKEWORD(FALSE, TRUE), lParam);
  135. }
  136. if (hwndActive == hwndSearch)
  137. SendMessage(hwndActive, FS_CHANGEDISPLAY, CD_PATH, 0L);
  138. }
  139. VOID APIENTRY CheckEscapes(LPSTR szFile)
  140. {
  141. CHAR szT[MAXPATHLEN];
  142. CHAR *p, *pT;
  143. #ifdef DBCS
  144. for (p = szFile; *p; p = (LPSTR)AnsiNext(p))
  145. #else
  146. for (p = szFile; *p; p++)
  147. #endif
  148. {
  149. switch (*p)
  150. {
  151. case ' ':
  152. case ',':
  153. case ';':
  154. case '^':
  155. case '"':
  156. {
  157. // this path contains an annoying character
  158. lstrcpy(szT,szFile);
  159. p = szFile;
  160. *p++ = '"';
  161. for (pT = szT; *pT; )
  162. {
  163. if (*pT == '^' || *pT == '"')
  164. *p++ = '^';
  165. #ifdef DBCS
  166. if (IsDBCSLeadByte(*p++ = *pT++))
  167. #endif
  168. *p++ = *pT++;
  169. }
  170. *p++ = '"';
  171. *p = 0;
  172. return;
  173. }
  174. }
  175. }
  176. }
  177. HWND APIENTRY GetRealParent(HWND hwnd)
  178. {
  179. // run up the parent chain until you find a hwnd
  180. // that doesn't have WS_CHILD set
  181. while (GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD)
  182. hwnd = (HWND)GetWindowLong(hwnd, GWL_HWNDPARENT);
  183. return hwnd;
  184. }
  185. VOID APIENTRY WFHelp(HWND hwnd)
  186. {
  187. if (!WinHelp(hwnd, szWinObjHelp, HELP_CONTEXT, dwContext)) {
  188. MyMessageBox(hwnd, IDS_WINFILE, IDS_WINHELPERR, MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
  189. }
  190. }
  191. // atoi with decimal comma seperators
  192. //
  193. //#ifdef INLIBRARY
  194. LPSTR APIENTRY AddCommas(LPSTR szBuf, DWORD dw)
  195. {
  196. CHAR szTemp[40];
  197. LPSTR pTemp;
  198. INT count, len;
  199. LPSTR p;
  200. ENTER("AddCommas");
  201. len = wsprintf(szTemp, "%ld", dw);
  202. pTemp = szTemp + len - 1;
  203. p = szBuf + len + ((len - 1) / 3);
  204. *p-- = TEXT('\0'); // null terimnate the string we are building
  205. count = 1;
  206. while (pTemp >= szTemp) {
  207. *p-- = *pTemp--;
  208. if (count == 3) {
  209. count = 1;
  210. if (p > szBuf)
  211. *p-- = szComma[0];
  212. } else
  213. count++;
  214. }
  215. LEAVE("AddCommas");
  216. return szBuf;
  217. }
  218. //#endif
  219. BOOL APIENTRY IsLastWindow()
  220. {
  221. HWND hwnd;
  222. INT count;
  223. count = 0;
  224. // count all non title/search windows to see if close is allowed
  225. for (hwnd = GetWindow(hwndMDIClient, GW_CHILD); hwnd; hwnd = GetWindow(hwnd, GW_HWNDNEXT))
  226. if (!GetWindow(hwnd, GW_OWNER) && ((INT)GetWindowLong(hwnd, GWL_TYPE) >= 0))
  227. count++;
  228. return count == 1;
  229. }
  230. // get connection information including disconnected drives
  231. //
  232. // in:
  233. // lpDev device name "A:" "LPT1:", etc.
  234. // fClosed if FALSE closed or error drives will be converted to
  235. // WN_SUCCESS return codes. if TRUE return not connected
  236. // and error state values (ie, the caller knows about not
  237. // connected and error state drives)
  238. // out:
  239. // lpPath filled with net name if return is WN_SUCCESS (or not connected/error)
  240. // returns:
  241. // WN_* error code
  242. WORD APIENTRY WFGetConnection(LPSTR lpDev, LPSTR lpPath, BOOL fClosed)
  243. {
  244. DWORD cb;
  245. UINT err;
  246. UINT caps;
  247. cb = 64;
  248. caps = WNetGetCaps(WNNC_CONNECTION);
  249. if (caps & WNNC_CON_GETCONNECTIONS)
  250. err = WNetGetConnection(lpDev,lpPath,&cb);
  251. else
  252. return WN_NOT_CONNECTED;
  253. if (err == WN_NOT_CONNECTED &&
  254. !(caps & WNNC_CON_RESTORECONNECTION))
  255. {
  256. if (GetProfileString(szNetwork,lpDev,szNULL,lpPath,64))
  257. err = WN_CONNECTION_CLOSED;
  258. }
  259. if (!fClosed)
  260. if (err == WN_CONNECTION_CLOSED || err == WN_DEVICE_ERROR)
  261. err = WN_SUCCESS;
  262. return (WORD)err;
  263. }
  264. // returns the number of this MDI window as well as returning
  265. // the text with the number stripped off
  266. //
  267. // returns:
  268. // 0 this title doesn't have a number
  269. // > 0 the title number
  270. // szTitle the title with the number stripped off
  271. INT APIENTRY GetMDIWindowText(HWND hWnd, LPSTR szTitle, INT size)
  272. {
  273. LPSTR lp, lpLast;
  274. ENTER("GetMDIWindowText");
  275. GetWindowText(hWnd, szTitle, size);
  276. lpLast = NULL;
  277. #ifdef DBCS
  278. for (lp = szTitle; *lp; lp = AnsiNext(lp))
  279. #else
  280. for (lp = szTitle; *lp; lp++)
  281. #endif
  282. if (*lp == ':')
  283. lpLast = lp;
  284. if (lpLast) {
  285. *lpLast++ = 0;
  286. PRINT(BF_PARMTRACE, "OUT: szTitle=%s", szTitle);
  287. PRINT(BF_PARMTRACE, "OUT: window#=%s", lpLast);
  288. LEAVE("GetMDIWindowText");
  289. return atoi(lpLast); // return the window number
  290. } else {
  291. TRACE(BF_PARMTRACE, "OUT: window#=0");
  292. LEAVE("GetMDIWindowText");
  293. return 0; // no number on this
  294. }
  295. }
  296. // set the MDI window text and add a ":#" on the end if
  297. // there is another window with the same title. this is to
  298. // avoid confusion when there are multiple MDI children
  299. // with the same title. be sure to use GetMDIWindowText to
  300. // strip off the number stuff.
  301. VOID APIENTRY SetMDIWindowText(HWND hWnd, LPSTR szTitle)
  302. {
  303. CHAR szTemp[MAXPATHLEN];
  304. CHAR szNumber[20];
  305. HWND hwnd;
  306. INT num, max_num;
  307. ENTER("SetMDIWindowText");
  308. PRINT(BF_PARMTRACE, "hWnd=%lx", hWnd);
  309. PRINT(BF_PARMTRACE, "IN: szTitle=%s", szTitle);
  310. max_num = 0;
  311. for (hwnd = GetWindow(hwndMDIClient, GW_CHILD); hwnd; hwnd = GetWindow(hwnd, GW_HWNDNEXT)) {
  312. num = GetMDIWindowText(hwnd, szTemp, sizeof(szTemp));
  313. if (!lstrcmp(szTemp, szTitle)) {
  314. if (hwnd == hWnd)
  315. continue;
  316. if (!num) {
  317. lstrcat(szTemp, ":1");
  318. // if (wTextAttribs & TA_LOWERCASE)
  319. // AnsiLower(szTemp);
  320. SetWindowText(hwnd, szTemp);
  321. num = 1;
  322. }
  323. max_num = max(max_num, num);
  324. }
  325. }
  326. if (max_num) {
  327. wsprintf(szNumber, ":%d", max_num+1);
  328. lstrcat(szTitle, szNumber);
  329. }
  330. // if (wTextAttribs & TA_LOWERCASE)
  331. // AnsiLower(szTitle);
  332. SetWindowText(hWnd, szTitle);
  333. PRINT(BF_PARMTRACE, "OUT: szTitle=%s", szTitle);
  334. LEAVE("SetMDIWindowText");
  335. }
  336. #define ISDIGIT(c) ((c) >= '0' && (c) <= '9')
  337. #ifdef INLIBRARY
  338. INT APIENTRY atoi(LPSTR sz)
  339. {
  340. INT n = 0;
  341. BOOL bNeg = FALSE;
  342. if (*sz == '-') {
  343. bNeg = TRUE;
  344. sz++;
  345. }
  346. while (ISDIGIT(*sz)) {
  347. n *= 10;
  348. n += *sz - '0';
  349. sz++;
  350. }
  351. return bNeg ? -n : n;
  352. }
  353. #endif
  354. // fills in rgiDrive[] and returns the number of drives
  355. INT APIENTRY UpdateDriveList()
  356. {
  357. INT i, cRealDrives = 0;
  358. DWORD dwDrives;
  359. dwDrives = GetLogicalDrives();
  360. for (i = 0; i < 26; i++) {
  361. if ((1 << i) & dwDrives) {
  362. rgiDrive[cRealDrives++] = i;
  363. rgiDriveType[i] = MGetDriveType(i);
  364. }
  365. else {
  366. rgiDrive[i] = 0;
  367. rgiDriveType[i] = -1; // invalidate the drivetype
  368. }
  369. if (apVolInfo[i]) { // sothat volinfo is refreshed
  370. LocalFree(apVolInfo[i]);
  371. apVolInfo[i] = NULL;
  372. }
  373. }
  374. return cRealDrives;
  375. }
  376. int FAR PASCAL GetBootDisk()
  377. {
  378. CHAR szTemp[MAXPATHLEN];
  379. #if 0
  380. if (wDOSversion >= 0x0400) {
  381. _asm {
  382. mov ax, 3305h ; get startup drive
  383. int 21h
  384. xor dh,dh ; clear high part
  385. dec dl ; convert to zero based (A=0)
  386. mov ax, dx
  387. }
  388. } else {
  389. #endif
  390. // well, close enough...
  391. GetWindowsDirectory(szTemp, sizeof(szTemp));
  392. return szTemp[0] - 'A';
  393. #if 0
  394. }
  395. #endif
  396. }
  397. //
  398. // IsCDROM() - determine if a drive is a CDROM drive
  399. //
  400. // iDrive drive index (0=A, 1=B, ...)
  401. //
  402. // return TRUE/FALSE
  403. //
  404. WORD APIENTRY IsCDRomDrive(INT iDrive)
  405. {
  406. if (rgiDriveType[iDrive] == DRIVE_CDROM)
  407. return(TRUE);
  408. return(FALSE);
  409. }
  410. // this is called for every drive at init time so it must
  411. // be sure to not trigget things like the phantom B: drive support
  412. //
  413. // iDrive is a zero based drive number (0 = A, 1 = B)
  414. WORD APIENTRY IsNetDrive(INT iDrive)
  415. {
  416. INT err;
  417. CHAR szDrive[3];
  418. CHAR szConn[64]; // this really should be WNBD_MAX_LENGTH
  419. // but this change would have to be many everywhere
  420. szDrive[0] = (CHAR)(iDrive+'A');
  421. szDrive[1] = ':';
  422. szDrive[2] = (CHAR)0;
  423. if (IsCDRomDrive(iDrive)) // this is bogus... move this out
  424. return 0;
  425. err = WFGetConnection(szDrive, szConn, TRUE);
  426. if (err == WN_SUCCESS)
  427. return 1;
  428. if (err == WN_CONNECTION_CLOSED || err == WN_DEVICE_ERROR)
  429. return 2;
  430. return 0;
  431. }
  432. BOOL APIENTRY IsRemovableDrive(register INT iDrive)
  433. {
  434. return DriveType(iDrive) == DRIVE_REMOVABLE;
  435. }
  436. BOOL APIENTRY IsRemoteDrive(register INT iDrive)
  437. {
  438. return DriveType(iDrive) == DRIVE_REMOTE;
  439. }
  440. // iDrive zero based drive number (A = 0)
  441. BOOL APIENTRY IsRamDrive(INT iDrive)
  442. {
  443. return DriveType(iDrive) == DRIVE_RAMDISK;
  444. }
  445. // get interesting stuff about a drive
  446. //
  447. // zero based drive numbers (0 = A, 1 = B)
  448. //
  449. DWORD APIENTRY GetClusterInfo(WORD drive)
  450. {
  451. #ifdef ORGCODE
  452. DevPB dpbDiskParms; /* Device Parameters */
  453. // try the fast way...
  454. memset(&dpbDiskParms, 0, sizeof(dpbDiskParms));
  455. if (!DeviceParameters(drive, &dpbDiskParms, IOCTL_GET_DPB))
  456. return MAKELONG((WORD)dpbDiskParms.BPB.secPerClus, dpbDiskParms.BPB.cbSec);
  457. // very slow way...
  458. _asm {
  459. mov ah,36h
  460. mov dx,drive
  461. inc dx ; make it 1 based.
  462. int 21h
  463. inc ax ; if Error, ax = -1, else, ax = sectors/cluster
  464. jz GCSdone ; Yup, Error. Return zero.
  465. dec ax ; Get back sectors/cluster.
  466. mov dx, cx ; cx = bytes/sector
  467. GCSdone:
  468. }
  469. #else
  470. UNREFERENCED_PARAMETER(drive);
  471. return 0;
  472. #endif
  473. }
  474. BOOL APIENTRY IsValidDisk(INT iDrive)
  475. {
  476. if (apVolInfo[iDrive] == NULL)
  477. FillVolumeInfo(iDrive);
  478. return(apVolInfo[iDrive] != NULL);
  479. }
  480. VOID APIENTRY GetVolShare(WORD wDrive, LPSTR szVolShare)
  481. {
  482. CHAR szDrive[5];
  483. szVolShare[0] = TEXT('\0');
  484. #ifdef OLD
  485. if (!IsCDRomDrive(wDrive))
  486. {
  487. szDrive[0] = (CHAR)('A'+ wDrive);
  488. szDrive[1] = ':';
  489. szDrive[2] = 0;
  490. if (WFGetConnection(szDrive,szVolShare,FALSE) != WN_SUCCESS) {
  491. GetVolumeLabel(wDrive, szVolShare, TRUE);
  492. OemToAnsi(szVolShare, szVolShare);
  493. }
  494. else
  495. lstrcpy(szVolShare,"CD-ROM");
  496. #else
  497. lstrcpy(szVolShare, "Objects");
  498. #endif
  499. }
  500. #ifdef LFN
  501. /*--------------------------------------------------------------------------*/
  502. /* */
  503. /* IsLFNSelected() - */
  504. /* */
  505. /*--------------------------------------------------------------------------*/
  506. BOOL APIENTRY IsLFNSelected()
  507. {
  508. HWND hwndActive;
  509. BOOL fDir;
  510. LPSTR p;
  511. hwndActive = (HWND)SendMessage(hwndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  512. p = (LPSTR)SendMessage(hwndActive, FS_GETSELECTION, 2, (LONG)&fDir);
  513. if (p) {
  514. LocalFree((HANDLE)p);
  515. }
  516. return(fDir);
  517. }
  518. #endif
  519. /*--------------------------------------------------------------------------*/
  520. /* */
  521. /* GetSelection() - */
  522. // caller must free lpstr returned.
  523. /* */
  524. /*--------------------------------------------------------------------------*/
  525. LPSTR APIENTRY GetSelection(INT iSelType)
  526. {
  527. HWND hwndActive;
  528. hwndActive = (HWND)SendMessage(hwndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  529. return (LPSTR)SendMessage(hwndActive,FS_GETSELECTION, (WPARAM)iSelType, 0L);
  530. }
  531. //
  532. // in:
  533. // pFrom pointer that is used as start of selection search.
  534. // on subsequent calls pass in the previous non NULL
  535. // return value
  536. //
  537. // out:
  538. // pTo buffer that receives the next file in the list
  539. // for non NULL return
  540. //
  541. // returns:
  542. // NULL if no more files in this list (szFile) is undefined
  543. // pointer to be passed to subsequent calls to this function
  544. // to enumerate thorough the file list
  545. //
  546. LPSTR APIENTRY GetNextFile(LPSTR pFrom, LPSTR pTo, INT cbMax)
  547. {
  548. INT i;
  549. ENTER("GetNextFile");
  550. PRINT(BF_PARMTRACE, "IN: pFrom=%s", pFrom);
  551. if (!pFrom)
  552. return NULL;
  553. /* Skip over leading spaces and commas. */
  554. while (*pFrom && (*pFrom == ' ' || *pFrom == ','))
  555. #ifdef DBCS
  556. pFrom = (LPSTR)AnsiNext(pFrom);
  557. #else
  558. pFrom++;
  559. #endif
  560. if (!*pFrom)
  561. return(NULL);
  562. if (*pFrom == '\"') {
  563. #ifdef DBCS
  564. pFrom = (LPSTR)AnsiNext(pFrom);
  565. #else
  566. pFrom++;
  567. #endif
  568. /* Find the next quote */
  569. for (i=0; *pFrom && *pFrom != '\"';)
  570. {
  571. if (*pFrom == '^')
  572. {
  573. #ifdef DBCS
  574. pFrom = (LPSTR)AnsiNext(pFrom)
  575. #else
  576. ++pFrom;
  577. #endif
  578. if (!*pFrom)
  579. break;
  580. }
  581. if (i < cbMax - 1)
  582. {
  583. #ifdef DBCS
  584. i++;
  585. if (IsDBCSLeadByte(*pTo++ = *pFrom++))
  586. #endif
  587. {
  588. i++;
  589. *pTo++ = *pFrom++;
  590. }
  591. }
  592. }
  593. #ifdef DBCS
  594. pFrom = (LPSTR)AnsiNext(pFrom);
  595. #else
  596. pFrom++;
  597. #endif
  598. } else {
  599. /* Find the next space or comma. */
  600. for (i=0; *pFrom && *pFrom != ' ' && *pFrom != ',';) {
  601. if (*pFrom == '^') {
  602. #ifdef DBCS
  603. pFrom = (LPSTR)AnsiNext(pFrom)
  604. #else
  605. ++pFrom;
  606. #endif
  607. if (!*pFrom)
  608. break;
  609. }
  610. if (i < cbMax - 1) {
  611. #ifdef DBCS
  612. i++;
  613. if (IsDBCSLeadByte(*pTo++ = *pFrom++))
  614. #endif
  615. {
  616. i++;
  617. *pTo++ = *pFrom++;
  618. }
  619. }
  620. }
  621. }
  622. *pTo = TEXT('\0');
  623. PRINT(BF_PARMTRACE, pTo ? "OUT: pTo=%s" : "OUT: pTo=NULL", pTo);
  624. LEAVE("GetNextFile");
  625. return(pFrom);
  626. }
  627. // sets the DOS current directory based on the currently active window
  628. VOID APIENTRY SetWindowDirectory()
  629. {
  630. CHAR szTemp[MAXPATHLEN];
  631. GetSelectedDirectory(0, szTemp);
  632. FixAnsiPathForDos(szTemp);
  633. SheChangeDir(szTemp);
  634. }
  635. /*--------------------------------------------------------------------------*/
  636. /* */
  637. /* SetDlgDirectory() - */
  638. /* */
  639. /*--------------------------------------------------------------------------*/
  640. /* Sets the IDD_DIR field of 'hDlg' to whatever the active window says is the
  641. * active directory.
  642. *
  643. * this does not really change the DOS current directory
  644. */
  645. VOID APIENTRY SetDlgDirectory(HWND hDlg, PSTR pszPath)
  646. {
  647. HDC hDC;
  648. INT dx;
  649. RECT rc;
  650. HWND hDlgItem;
  651. HANDLE hFont;
  652. CHAR szPath[MAXPATHLEN+5];
  653. CHAR szTemp[MAXPATHLEN+20];
  654. ENTER("SetDlgDirectory");
  655. if (pszPath)
  656. lstrcpy(szPath, pszPath);
  657. else
  658. GetSelectedDirectory(0, szPath);
  659. /* Make sure that the current directory fits inside the static text field. */
  660. hDlgItem = GetDlgItem(hDlg, IDD_DIR);
  661. GetClientRect(hDlgItem, &rc);
  662. if (LoadString(hAppInstance, IDS_CURDIRIS, szMessage, sizeof(szMessage))) {
  663. hDC = GetDC(hDlg);
  664. hFont = (HANDLE)SendMessage(hDlgItem, WM_GETFONT, 0, 0L);
  665. if (hFont = SelectObject(hDC, hFont)) {
  666. MGetTextExtent(hDC, szMessage, lstrlen(szMessage), &dx, NULL);
  667. CompactPath(hDC, szPath, (WORD)(rc.right-rc.left-dx));
  668. }
  669. SelectObject(hDC, hFont);
  670. ReleaseDC(hDlg, hDC);
  671. wsprintf(szTemp, szMessage, (LPSTR)szPath);
  672. SetDlgItemText(hDlg, IDD_DIR, szTemp);
  673. }
  674. LEAVE("SetDlgDirectory");
  675. }
  676. /*--------------------------------------------------------------------------*/
  677. /* */
  678. /* WritePrivateProfileBool() - */
  679. /* */
  680. /*--------------------------------------------------------------------------*/
  681. VOID APIENTRY WritePrivateProfileBool(LPSTR szKey, BOOL bParam)
  682. {
  683. CHAR szBool[6];
  684. wsprintf(szBool, "%d", bParam);
  685. WritePrivateProfileString(szSettings, szKey, szBool, szTheINIFile);
  686. }
  687. /*--------------------------------------------------------------------------*/
  688. /* */
  689. /* WFQueryAbort() - */
  690. /* */
  691. /*--------------------------------------------------------------------------*/
  692. BOOL APIENTRY WFQueryAbort()
  693. {
  694. MSG msg;
  695. while (PeekMessage(&msg, NULL, 0, 0, TRUE))
  696. {
  697. if (!IsDialogMessage(hdlgProgress, &msg))
  698. DispatchMessage(&msg);
  699. }
  700. return(bUserAbort);
  701. }
  702. /*--------------------------------------------------------------------------*/
  703. /* */
  704. /* IsWild() - */
  705. /* */
  706. /*--------------------------------------------------------------------------*/
  707. /* Returns TRUE iff the path contains * or ? */
  708. BOOL APIENTRY IsWild(LPSTR lpszPath)
  709. {
  710. while (*lpszPath)
  711. {
  712. if (*lpszPath == '?' || *lpszPath == '*')
  713. return(TRUE);
  714. #ifdef DBCS
  715. lpszPath = AnsiNext(lpszPath);
  716. #else
  717. lpszPath++;
  718. #endif
  719. }
  720. return(FALSE);
  721. }
  722. /*--------------------------------------------------------------------------*/
  723. /* */
  724. /* CheckSlashies() - */
  725. /* */
  726. /*--------------------------------------------------------------------------*/
  727. /* Replaces frontslashes (evil) with backslashes (good). */
  728. VOID APIENTRY CheckSlashies(LPSTR lpT)
  729. {
  730. while (*lpT)
  731. {
  732. if (*lpT == '/')
  733. *lpT = '\\';
  734. #ifdef DBCS
  735. lpT = AnsiNext(lpT);
  736. #else
  737. lpT++;
  738. #endif
  739. }
  740. }
  741. /*--------------------------------------------------------------------------*/
  742. /* */
  743. /* AddBackslash() - */
  744. /* */
  745. /*--------------------------------------------------------------------------*/
  746. /* Ensures that a path ends with a backslash. */
  747. VOID APIENTRY AddBackslash(LPSTR lpszPath)
  748. {
  749. ENTER("AddBackslash");
  750. PRINT(BF_PARMTRACE, "IN: lpszPath=%s", lpszPath);
  751. if (*AnsiPrev(lpszPath,lpszPath+lstrlen(lpszPath)) != '\\')
  752. lstrcat(lpszPath, "\\");
  753. PRINT(BF_PARMTRACE, "OUT: lpszPath=%s", lpszPath);
  754. LEAVE("AddBackslash");
  755. }
  756. /*--------------------------------------------------------------------------*/
  757. /* */
  758. /* StripBackslash() - */
  759. /* */
  760. /*--------------------------------------------------------------------------*/
  761. /* Removes a trailing backslash from a proper directory name UNLESS it is
  762. * the root directory. Assumes a fully qualified directory path.
  763. */
  764. VOID APIENTRY StripBackslash(LPSTR lpszPath)
  765. {
  766. register WORD len;
  767. #ifdef DBCS
  768. len = lstrlen(lpszPath) - (IsDBCSLeadByte(*AnsiPrev(lpszPath,lpszPath+lstrlen(lpszPath))) ? 2 : 1);
  769. #else
  770. len = (WORD)(lstrlen(lpszPath) - 1);
  771. #endif
  772. if ((len == 2) || (lpszPath[len] != '\\'))
  773. return;
  774. lpszPath[len] = TEXT('\0');
  775. }
  776. /*--------------------------------------------------------------------------*/
  777. /* */
  778. /* StripFilespec() - */
  779. /* */
  780. /*--------------------------------------------------------------------------*/
  781. /* Remove the filespec portion from a path (including the backslash). */
  782. VOID APIENTRY StripFilespec(LPSTR lpszPath)
  783. {
  784. LPSTR p;
  785. #ifdef DBCS
  786. p = lpszPath + lstrlen(lpszPath);
  787. while ((*p != '\\') && (*p != ':') && (p != lpszPath))
  788. p = AnsiPrev(lpszPath, p);
  789. #else
  790. p = lpszPath + lstrlen(lpszPath);
  791. while ((*p != '\\') && (*p != ':') && (p != lpszPath))
  792. p--;
  793. #endif
  794. if (*p == ':')
  795. p++;
  796. /* Don't strip backslash from root directory entry. */
  797. if (p != lpszPath)
  798. {
  799. if ((*p == '\\') && (*(p-1) == ':'))
  800. p++;
  801. }
  802. else
  803. p++;
  804. *p = TEXT('\0');
  805. }
  806. /*--------------------------------------------------------------------------*/
  807. /* */
  808. /* StripPath() - */
  809. /* */
  810. /*--------------------------------------------------------------------------*/
  811. /* Extract only the filespec portion from a path. */
  812. VOID APIENTRY StripPath(LPSTR lpszPath)
  813. {
  814. LPSTR p;
  815. ENTER("StripPath");
  816. PRINT(BF_PARMTRACE, "IN: lpszPath=%s", lpszPath);
  817. p = lpszPath + lstrlen(lpszPath);
  818. #ifdef DBCS
  819. while ((*p != '\\') && (*p != ':') && (p != lpszPath))
  820. p = AnsiPrev(lpszPath, p);
  821. #else
  822. while ((*p != '\\') && (*p != ':') && (p != lpszPath))
  823. p--;
  824. #endif
  825. if (p != lpszPath || *p == '\\')
  826. p++;
  827. if (p != lpszPath)
  828. lstrcpy(lpszPath, p);
  829. PRINT(BF_PARMTRACE, "OUT: lpszPath=%s", lpszPath);
  830. LEAVE("StripPath");
  831. }
  832. /*--------------------------------------------------------------------------*/
  833. /* */
  834. /* GetExtension() - */
  835. /* */
  836. /*--------------------------------------------------------------------------*/
  837. /* Returns the extension part of a filename. */
  838. LPSTR APIENTRY GetExtension(LPSTR pszFile)
  839. {
  840. PSTR p, pSave = NULL;
  841. p = pszFile;
  842. while (*p)
  843. {
  844. if (*p == '.')
  845. pSave = p;
  846. #ifdef DBCS
  847. p = (LPSTR)AnsiNext(p);
  848. #else
  849. p++;
  850. #endif
  851. }
  852. if (!pSave)
  853. return(p);
  854. #ifdef DBCS
  855. return (LPSTR)AnsiNext(pSave);
  856. #else
  857. return pSave+1;
  858. #endif
  859. }
  860. /*--------------------------------------------------------------------------*/
  861. /* */
  862. /* FindExtensionInList() - */
  863. /* */
  864. /*--------------------------------------------------------------------------*/
  865. /* Returns TRUE if 'lpszExt' is somewhere in 'pszList'. */
  866. BOOL APIENTRY FindExtensionInList(LPSTR pszExt, LPSTR pszList)
  867. {
  868. LPSTR p2;
  869. CHAR ch;
  870. while (*pszList)
  871. {
  872. /* Move to the next item in the list. */
  873. while ((*pszList) && (*pszList == ' '))
  874. #ifdef DBCS
  875. pszList = (LPSTR)AnsiNext(pszList);
  876. #else
  877. pszList++;
  878. #endif
  879. if (!*pszList)
  880. break;
  881. /* NULL-terminate this item. */
  882. #ifdef DBCS
  883. p2 = (LPSTR)AnsiNext(pszList);
  884. #else
  885. p2 = pszList+1;
  886. #endif
  887. while ((*p2) && (*p2 != ' '))
  888. #ifdef DBCS
  889. p2 = (LPSTR)AnsiNext(p2);
  890. #else
  891. p2++;
  892. #endif
  893. ch = *p2;
  894. *p2 = TEXT('\0');
  895. if (!lstrcmpi(pszExt, pszList))
  896. {
  897. *p2 = ch;
  898. return(TRUE);
  899. }
  900. *p2 = ch;
  901. pszList = p2;
  902. }
  903. return(FALSE);
  904. }
  905. /*--------------------------------------------------------------------------*/
  906. /* */
  907. /* MyMessageBox() - */
  908. /* */
  909. /*--------------------------------------------------------------------------*/
  910. INT APIENTRY MyMessageBox(HWND hWnd, WORD idTitle, WORD idMessage, WORD wStyle)
  911. {
  912. CHAR szTemp[MAXMESSAGELEN];
  913. HWND hwndT;
  914. LoadString(hAppInstance, idTitle, szTitle, sizeof(szTitle));
  915. if (idMessage < 32)
  916. {
  917. LoadString(hAppInstance, IDS_UNKNOWNMSG, szTemp, sizeof(szTemp));
  918. wsprintf(szMessage, szTemp, idMessage);
  919. }
  920. else
  921. LoadString(hAppInstance, idMessage, szMessage, sizeof(szMessage));
  922. if (hWnd)
  923. hwndT = GetLastActivePopup(hWnd);
  924. else
  925. hwndT = hWnd;
  926. return MessageBox(hwndT, szMessage, szTitle, wStyle | MB_TASKMODAL);
  927. }
  928. /*--------------------------------------------------------------------------*/
  929. /* */
  930. /* ExecProgram() - */
  931. /* */
  932. /* all strings are OEM */
  933. /*--------------------------------------------------------------------------*/
  934. /* Returns 0 for success. Otherwise returns a IDS_ string code. */
  935. WORD APIENTRY ExecProgram(LPSTR lpPath, LPSTR lpParms, LPSTR lpDir, BOOL bLoadIt)
  936. {
  937. WORD ret;
  938. INT iCurCount;
  939. INT i;
  940. HCURSOR hCursor;
  941. ENTER("ExecProgram");
  942. ret = 0;
  943. hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  944. iCurCount = ShowCursor(TRUE) - 1;
  945. /* open the object
  946. */
  947. if (lpPath)
  948. OemToAnsi(lpPath, lpPath);
  949. if (lpParms)
  950. OemToAnsi(lpParms, lpParms);
  951. if (lpDir)
  952. OemToAnsi(lpDir, lpDir);
  953. // Shell Execute takes ansi string.
  954. //
  955. // BUGBUG: WIN31 and NT have different RealShellExecute params....
  956. ret = (WORD)RealShellExecute(hwndFrame, NULL, lpPath, lpParms, lpDir, NULL, NULL, NULL, (WORD)(bLoadIt ? SW_SHOWMINNOACTIVE : SW_SHOWNORMAL), NULL);
  957. DosResetDTAAddress(); // undo any bad things COMMDLG did
  958. if (lpPath)
  959. AnsiToOem(lpPath, lpPath);
  960. if (lpParms)
  961. AnsiToOem(lpParms, lpParms);
  962. if (lpDir)
  963. AnsiToOem(lpDir, lpDir);
  964. switch (ret) {
  965. case 0:
  966. case 8:
  967. ret = IDS_NOMEMORYMSG;
  968. break;
  969. case 2:
  970. ret = IDS_FILENOTFOUNDMSG;
  971. break;
  972. case 3:
  973. case 5: // access denied
  974. ret = IDS_BADPATHMSG;
  975. break;
  976. case 4:
  977. ret = IDS_MANYOPENFILESMSG;
  978. break;
  979. case 10:
  980. ret = IDS_NEWWINDOWSMSG;
  981. break;
  982. case 12:
  983. ret = IDS_OS2APPMSG;
  984. break;
  985. case 15:
  986. /* KERNEL has already put up a messagebox for this one. */
  987. ret = 0;
  988. break;
  989. case 16:
  990. ret = IDS_MULTIPLEDSMSG;
  991. break;
  992. case 18:
  993. ret = IDS_PMODEONLYMSG;
  994. break;
  995. case 19:
  996. ret = IDS_COMPRESSEDEXE;
  997. break;
  998. case 20:
  999. ret = IDS_INVALIDDLL;
  1000. break;
  1001. case SE_ERR_SHARE:
  1002. ret = IDS_SHAREERROR;
  1003. break;
  1004. case SE_ERR_ASSOCINCOMPLETE:
  1005. ret = IDS_ASSOCINCOMPLETE;
  1006. break;
  1007. case SE_ERR_DDETIMEOUT:
  1008. case SE_ERR_DDEFAIL:
  1009. case SE_ERR_DDEBUSY:
  1010. ret = IDS_DDEFAIL;
  1011. break;
  1012. case SE_ERR_NOASSOC:
  1013. ret = IDS_NOASSOCMSG;
  1014. break;
  1015. default:
  1016. if (ret < 32)
  1017. goto EPExit;
  1018. if (bMinOnRun && !bLoadIt)
  1019. ShowWindow(hwndFrame, SW_SHOWMINNOACTIVE);
  1020. ret = 0;
  1021. }
  1022. EPExit:
  1023. i = ShowCursor(FALSE);
  1024. #if 0
  1025. /* Make sure that the cursor count is still balanced. */
  1026. if (i != iCurCount)
  1027. ShowCursor(TRUE);
  1028. #endif
  1029. SetCursor(hCursor);
  1030. PRINT(BF_PARMTRACE, "OUT: ret=%ud", ret);
  1031. LEAVE("ExecProgram");
  1032. return ret;
  1033. }
  1034. /*--------------------------------------------------------------------------*/
  1035. /* */
  1036. /* IsProgramFile() - */
  1037. /* */
  1038. /*--------------------------------------------------------------------------*/
  1039. /* Returns TRUE is the Path points to a file which has one of the extentions
  1040. * listed in the "Programs=" portions of WIN.INI.
  1041. */
  1042. BOOL APIENTRY IsProgramFile(LPSTR lpszPath)
  1043. {
  1044. LPSTR szExt;
  1045. CHAR szTemp[MAXPATHLEN];
  1046. /* Move the string into our own DS. */
  1047. lstrcpy(szTemp, lpszPath);
  1048. /* Get the file's extension. */
  1049. StripPath(szTemp);
  1050. szExt = GetExtension(szTemp);
  1051. if (!*szExt)
  1052. {
  1053. /* The specified path didn't have an extention. It can't be a program. */
  1054. return(FALSE);
  1055. }
  1056. return FindExtensionInList(szExt, szPrograms);
  1057. }
  1058. /*--------------------------------------------------------------------------*/
  1059. /* */
  1060. /* IsDocument() - */
  1061. /* */
  1062. /*--------------------------------------------------------------------------*/
  1063. /* Returns TRUE is the Path points to a file which has one of the extentions
  1064. * listed in the "Documents=" portions of WIN.INI or one which has an Association.
  1065. */
  1066. BOOL APIENTRY IsDocument(LPSTR lpszPath)
  1067. {
  1068. LPSTR szExt;
  1069. CHAR szTemp[MAXPATHLEN];
  1070. /* Move the string into our own DS. */
  1071. lstrcpy(szTemp, lpszPath);
  1072. /* Get the file's extension. */
  1073. StripPath(szTemp);
  1074. szExt = GetExtension(szTemp);
  1075. if (!*szExt)
  1076. {
  1077. /* The specified path didn't have an extention. It can't be a program. */
  1078. return(FALSE);
  1079. }
  1080. return FindExtensionInList(szExt, szDocuments);
  1081. }