mirror of https://github.com/lianthony/NT4.0
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
1379 lines
34 KiB
/****************************************************************************/
|
|
/* */
|
|
/* WFUTIL.C - */
|
|
/* */
|
|
/* Windows File System String Utility Functions */
|
|
/* */
|
|
/****************************************************************************/
|
|
|
|
#include "winfile.h"
|
|
#include "lfn.h"
|
|
#include "winnet.h"
|
|
#include "wnetcaps.h" // WNetGetCaps()
|
|
#include "stdlib.h"
|
|
|
|
int rgiDriveType[26];
|
|
PSTR CurDirCache[26];
|
|
|
|
// cache GetDriveType calls for speed
|
|
|
|
INT NEAR PASCAL DriveType(INT iDrive)
|
|
{
|
|
if (rgiDriveType[iDrive] != -1)
|
|
return rgiDriveType[iDrive];
|
|
|
|
return rgiDriveType[iDrive] = MGetDriveType(iDrive);
|
|
}
|
|
|
|
VOID NEAR PASCAL InvalidateDriveType()
|
|
{
|
|
INT i;
|
|
|
|
for (i = 0; i < 26; i++)
|
|
rgiDriveType[i] = -1;
|
|
}
|
|
|
|
// iDrive zero based drive number (0 = A, 1 = B)
|
|
// returns:
|
|
// TRUE we have it saved pszPath gets path
|
|
// FALSE we don't have it saved
|
|
|
|
BOOL APIENTRY GetSavedDirectory(INT iDrive, PSTR pszPath)
|
|
{
|
|
|
|
if (CurDirCache[iDrive]) {
|
|
lstrcpy(pszPath, CurDirCache[iDrive]);
|
|
return TRUE;
|
|
} else
|
|
return FALSE;
|
|
}
|
|
|
|
VOID APIENTRY SaveDirectory(PSTR pszPath)
|
|
{
|
|
INT i;
|
|
|
|
i = DRIVEID(pszPath);
|
|
|
|
if (CurDirCache[i])
|
|
LocalFree((HANDLE)CurDirCache[i]);
|
|
|
|
CurDirCache[i] = (PSTR)LocalAlloc(LPTR, lstrlen(pszPath)+1);
|
|
|
|
if (CurDirCache[i])
|
|
lstrcpy(CurDirCache[i], pszPath);
|
|
}
|
|
|
|
/*
|
|
* GetSelectedDrive() -
|
|
*
|
|
* Get the selected drive from the currently active window
|
|
*
|
|
* should be in wfutil.c
|
|
*/
|
|
|
|
INT APIENTRY GetSelectedDrive()
|
|
{
|
|
HWND hwnd;
|
|
|
|
hwnd = (HWND)SendMessage(hwndMDIClient,WM_MDIGETACTIVE,0,0L);
|
|
return (INT)SendMessage(hwnd,FS_GETDRIVE,0,0L) - (INT)'A';
|
|
}
|
|
|
|
/*
|
|
* GetSelectedDirectory() -
|
|
*
|
|
* Gets the directory selected for the drive. uses the windows
|
|
* z-order to give precidence to windows higher in the order.
|
|
*
|
|
* works like GetCurrentDirectory() except it looks through
|
|
* the window list for directories first (and returns ANSI)
|
|
*
|
|
* returns:
|
|
* lpDir ANSI string of current dir
|
|
*/
|
|
|
|
VOID APIENTRY GetSelectedDirectory(WORD iDrive, PSTR pszDir)
|
|
{
|
|
HWND hwnd;
|
|
WORD iDriveT;
|
|
|
|
if (iDrive) {
|
|
for (hwnd = GetWindow(hwndMDIClient,GW_CHILD);
|
|
hwnd;
|
|
hwnd = GetWindow(hwnd,GW_HWNDNEXT)) {
|
|
iDriveT = (WORD)SendMessage(hwnd,FS_GETDRIVE,0,0L);
|
|
if (iDrive == (WORD)(iDriveT - 'A' + 1))
|
|
goto hwndfound;
|
|
}
|
|
if (!GetSavedDirectory(iDrive - 1, pszDir)) {
|
|
SheGetDir(iDrive,pszDir);
|
|
OemToAnsi(pszDir,pszDir);
|
|
}
|
|
return;
|
|
} else
|
|
hwnd = (HWND)SendMessage(hwndMDIClient,WM_MDIGETACTIVE,0,0L);
|
|
|
|
hwndfound:
|
|
SendMessage(hwnd,FS_GETDIRECTORY,MAXPATHLEN,(LONG)(LPSTR)pszDir);
|
|
|
|
StripBackslash(pszDir);
|
|
}
|
|
|
|
|
|
// avoid confusion in DOSs upper case mapping by converting to
|
|
// upper case before passing down to dos
|
|
|
|
VOID APIENTRY FixAnsiPathForDos(LPSTR szPath)
|
|
{
|
|
#ifdef LFN
|
|
if (GetNameType(szPath) == FILE_83_CI)
|
|
#endif
|
|
AnsiUpper(szPath);
|
|
|
|
AnsiToOem(szPath, szPath);
|
|
}
|
|
|
|
// refresh a MDI child window (works for any type of mdi child)
|
|
|
|
VOID APIENTRY RefreshWindow(HWND hwndActive)
|
|
{
|
|
HWND hwndTree, hwndDir;
|
|
DWORD lParam;
|
|
CHAR szDir[MAXPATHLEN];
|
|
INT iDrive;
|
|
|
|
cDrives = UpdateDriveList(); // updates rgiDrive[]
|
|
InitDriveBitmaps();
|
|
|
|
// make sure the thing is still there (floppy drive, net drive)
|
|
|
|
iDrive = (INT)GetWindowLong(hwndActive, GWL_TYPE);
|
|
if ((iDrive >= 0) && !CheckDrive(hwndActive, iDrive))
|
|
return;
|
|
|
|
// update the dir part first so tree can steal later
|
|
|
|
if (hwndDir = HasDirWindow(hwndActive))
|
|
SendMessage(hwndDir, FS_CHANGEDISPLAY, CD_PATH, 0L);
|
|
|
|
if (hwndTree = HasTreeWindow(hwndActive)) {
|
|
// remember the current directory
|
|
SendMessage(hwndActive, FS_GETDIRECTORY, sizeof(szDir), (LONG)(LPSTR)szDir);
|
|
|
|
// update the drives windows
|
|
SendMessage(hwndActive, FS_CHANGEDRIVES, 0, 0L);
|
|
|
|
if (IsValidDisk(szDir[0] - 'A'))
|
|
lParam = (LONG)szDir;
|
|
else
|
|
lParam = 0;
|
|
|
|
// update the tree
|
|
SendMessage(hwndTree, TC_SETDRIVE, MAKEWORD(FALSE, TRUE), lParam);
|
|
}
|
|
|
|
if (hwndActive == hwndSearch)
|
|
SendMessage(hwndActive, FS_CHANGEDISPLAY, CD_PATH, 0L);
|
|
}
|
|
|
|
|
|
VOID APIENTRY CheckEscapes(LPSTR szFile)
|
|
{
|
|
CHAR szT[MAXPATHLEN];
|
|
CHAR *p, *pT;
|
|
|
|
#ifdef DBCS
|
|
for (p = szFile; *p; p = (LPSTR)AnsiNext(p))
|
|
#else
|
|
for (p = szFile; *p; p++)
|
|
#endif
|
|
{
|
|
switch (*p)
|
|
{
|
|
case ' ':
|
|
case ',':
|
|
case ';':
|
|
case '^':
|
|
case '"':
|
|
{
|
|
// this path contains an annoying character
|
|
lstrcpy(szT,szFile);
|
|
p = szFile;
|
|
*p++ = '"';
|
|
for (pT = szT; *pT; )
|
|
{
|
|
if (*pT == '^' || *pT == '"')
|
|
*p++ = '^';
|
|
#ifdef DBCS
|
|
if (IsDBCSLeadByte(*p++ = *pT++))
|
|
#endif
|
|
*p++ = *pT++;
|
|
}
|
|
*p++ = '"';
|
|
*p = 0;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
HWND APIENTRY GetRealParent(HWND hwnd)
|
|
{
|
|
// run up the parent chain until you find a hwnd
|
|
// that doesn't have WS_CHILD set
|
|
|
|
while (GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD)
|
|
hwnd = (HWND)GetWindowLong(hwnd, GWL_HWNDPARENT);
|
|
|
|
return hwnd;
|
|
}
|
|
|
|
VOID APIENTRY WFHelp(HWND hwnd)
|
|
{
|
|
if (!WinHelp(hwnd, szWinObjHelp, HELP_CONTEXT, dwContext)) {
|
|
MyMessageBox(hwnd, IDS_WINFILE, IDS_WINHELPERR, MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
|
|
}
|
|
|
|
}
|
|
|
|
// atoi with decimal comma seperators
|
|
//
|
|
|
|
//#ifdef INLIBRARY
|
|
LPSTR APIENTRY AddCommas(LPSTR szBuf, DWORD dw)
|
|
{
|
|
CHAR szTemp[40];
|
|
LPSTR pTemp;
|
|
INT count, len;
|
|
LPSTR p;
|
|
|
|
ENTER("AddCommas");
|
|
|
|
len = wsprintf(szTemp, "%ld", dw);
|
|
|
|
pTemp = szTemp + len - 1;
|
|
|
|
p = szBuf + len + ((len - 1) / 3);
|
|
|
|
*p-- = TEXT('\0'); // null terimnate the string we are building
|
|
|
|
count = 1;
|
|
while (pTemp >= szTemp) {
|
|
*p-- = *pTemp--;
|
|
if (count == 3) {
|
|
count = 1;
|
|
if (p > szBuf)
|
|
*p-- = szComma[0];
|
|
} else
|
|
count++;
|
|
}
|
|
|
|
LEAVE("AddCommas");
|
|
return szBuf;
|
|
}
|
|
//#endif
|
|
|
|
|
|
BOOL APIENTRY IsLastWindow()
|
|
{
|
|
HWND hwnd;
|
|
INT count;
|
|
|
|
count = 0;
|
|
|
|
// count all non title/search windows to see if close is allowed
|
|
|
|
for (hwnd = GetWindow(hwndMDIClient, GW_CHILD); hwnd; hwnd = GetWindow(hwnd, GW_HWNDNEXT))
|
|
if (!GetWindow(hwnd, GW_OWNER) && ((INT)GetWindowLong(hwnd, GWL_TYPE) >= 0))
|
|
count++;
|
|
|
|
return count == 1;
|
|
}
|
|
|
|
// get connection information including disconnected drives
|
|
//
|
|
// in:
|
|
// lpDev device name "A:" "LPT1:", etc.
|
|
// fClosed if FALSE closed or error drives will be converted to
|
|
// WN_SUCCESS return codes. if TRUE return not connected
|
|
// and error state values (ie, the caller knows about not
|
|
// connected and error state drives)
|
|
// out:
|
|
// lpPath filled with net name if return is WN_SUCCESS (or not connected/error)
|
|
// returns:
|
|
// WN_* error code
|
|
|
|
WORD APIENTRY WFGetConnection(LPSTR lpDev, LPSTR lpPath, BOOL fClosed)
|
|
{
|
|
DWORD cb;
|
|
UINT err;
|
|
UINT caps;
|
|
|
|
cb = 64;
|
|
|
|
caps = WNetGetCaps(WNNC_CONNECTION);
|
|
if (caps & WNNC_CON_GETCONNECTIONS)
|
|
err = WNetGetConnection(lpDev,lpPath,&cb);
|
|
else
|
|
return WN_NOT_CONNECTED;
|
|
|
|
if (err == WN_NOT_CONNECTED &&
|
|
!(caps & WNNC_CON_RESTORECONNECTION))
|
|
{
|
|
if (GetProfileString(szNetwork,lpDev,szNULL,lpPath,64))
|
|
err = WN_CONNECTION_CLOSED;
|
|
}
|
|
|
|
if (!fClosed)
|
|
if (err == WN_CONNECTION_CLOSED || err == WN_DEVICE_ERROR)
|
|
err = WN_SUCCESS;
|
|
|
|
return (WORD)err;
|
|
}
|
|
|
|
|
|
|
|
// returns the number of this MDI window as well as returning
|
|
// the text with the number stripped off
|
|
//
|
|
// returns:
|
|
// 0 this title doesn't have a number
|
|
// > 0 the title number
|
|
// szTitle the title with the number stripped off
|
|
|
|
INT APIENTRY GetMDIWindowText(HWND hWnd, LPSTR szTitle, INT size)
|
|
{
|
|
LPSTR lp, lpLast;
|
|
|
|
ENTER("GetMDIWindowText");
|
|
|
|
GetWindowText(hWnd, szTitle, size);
|
|
|
|
lpLast = NULL;
|
|
|
|
#ifdef DBCS
|
|
for (lp = szTitle; *lp; lp = AnsiNext(lp))
|
|
#else
|
|
for (lp = szTitle; *lp; lp++)
|
|
#endif
|
|
if (*lp == ':')
|
|
lpLast = lp;
|
|
|
|
if (lpLast) {
|
|
*lpLast++ = 0;
|
|
PRINT(BF_PARMTRACE, "OUT: szTitle=%s", szTitle);
|
|
PRINT(BF_PARMTRACE, "OUT: window#=%s", lpLast);
|
|
LEAVE("GetMDIWindowText");
|
|
return atoi(lpLast); // return the window number
|
|
} else {
|
|
TRACE(BF_PARMTRACE, "OUT: window#=0");
|
|
LEAVE("GetMDIWindowText");
|
|
return 0; // no number on this
|
|
}
|
|
}
|
|
|
|
// set the MDI window text and add a ":#" on the end if
|
|
// there is another window with the same title. this is to
|
|
// avoid confusion when there are multiple MDI children
|
|
// with the same title. be sure to use GetMDIWindowText to
|
|
// strip off the number stuff.
|
|
|
|
VOID APIENTRY SetMDIWindowText(HWND hWnd, LPSTR szTitle)
|
|
{
|
|
CHAR szTemp[MAXPATHLEN];
|
|
CHAR szNumber[20];
|
|
HWND hwnd;
|
|
INT num, max_num;
|
|
|
|
ENTER("SetMDIWindowText");
|
|
PRINT(BF_PARMTRACE, "hWnd=%lx", hWnd);
|
|
PRINT(BF_PARMTRACE, "IN: szTitle=%s", szTitle);
|
|
|
|
max_num = 0;
|
|
|
|
for (hwnd = GetWindow(hwndMDIClient, GW_CHILD); hwnd; hwnd = GetWindow(hwnd, GW_HWNDNEXT)) {
|
|
|
|
num = GetMDIWindowText(hwnd, szTemp, sizeof(szTemp));
|
|
|
|
if (!lstrcmp(szTemp, szTitle)) {
|
|
|
|
if (hwnd == hWnd)
|
|
continue;
|
|
|
|
if (!num) {
|
|
lstrcat(szTemp, ":1");
|
|
// if (wTextAttribs & TA_LOWERCASE)
|
|
// AnsiLower(szTemp);
|
|
SetWindowText(hwnd, szTemp);
|
|
num = 1;
|
|
}
|
|
max_num = max(max_num, num);
|
|
}
|
|
}
|
|
|
|
if (max_num) {
|
|
wsprintf(szNumber, ":%d", max_num+1);
|
|
lstrcat(szTitle, szNumber);
|
|
}
|
|
|
|
// if (wTextAttribs & TA_LOWERCASE)
|
|
// AnsiLower(szTitle);
|
|
SetWindowText(hWnd, szTitle);
|
|
PRINT(BF_PARMTRACE, "OUT: szTitle=%s", szTitle);
|
|
LEAVE("SetMDIWindowText");
|
|
}
|
|
|
|
|
|
#define ISDIGIT(c) ((c) >= '0' && (c) <= '9')
|
|
#ifdef INLIBRARY
|
|
INT APIENTRY atoi(LPSTR sz)
|
|
{
|
|
INT n = 0;
|
|
BOOL bNeg = FALSE;
|
|
|
|
if (*sz == '-') {
|
|
bNeg = TRUE;
|
|
sz++;
|
|
}
|
|
|
|
while (ISDIGIT(*sz)) {
|
|
n *= 10;
|
|
n += *sz - '0';
|
|
sz++;
|
|
}
|
|
return bNeg ? -n : n;
|
|
}
|
|
#endif
|
|
|
|
// fills in rgiDrive[] and returns the number of drives
|
|
|
|
INT APIENTRY UpdateDriveList()
|
|
{
|
|
INT i, cRealDrives = 0;
|
|
DWORD dwDrives;
|
|
|
|
dwDrives = GetLogicalDrives();
|
|
|
|
for (i = 0; i < 26; i++) {
|
|
if ((1 << i) & dwDrives) {
|
|
rgiDrive[cRealDrives++] = i;
|
|
rgiDriveType[i] = MGetDriveType(i);
|
|
}
|
|
else {
|
|
rgiDrive[i] = 0;
|
|
rgiDriveType[i] = -1; // invalidate the drivetype
|
|
}
|
|
|
|
if (apVolInfo[i]) { // sothat volinfo is refreshed
|
|
LocalFree(apVolInfo[i]);
|
|
apVolInfo[i] = NULL;
|
|
}
|
|
}
|
|
|
|
return cRealDrives;
|
|
}
|
|
|
|
int FAR PASCAL GetBootDisk()
|
|
{
|
|
CHAR szTemp[MAXPATHLEN];
|
|
|
|
#if 0
|
|
if (wDOSversion >= 0x0400) {
|
|
_asm {
|
|
mov ax, 3305h ; get startup drive
|
|
int 21h
|
|
xor dh,dh ; clear high part
|
|
dec dl ; convert to zero based (A=0)
|
|
mov ax, dx
|
|
}
|
|
} else {
|
|
#endif
|
|
|
|
// well, close enough...
|
|
GetWindowsDirectory(szTemp, sizeof(szTemp));
|
|
return szTemp[0] - 'A';
|
|
#if 0
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
//
|
|
// IsCDROM() - determine if a drive is a CDROM drive
|
|
//
|
|
// iDrive drive index (0=A, 1=B, ...)
|
|
//
|
|
// return TRUE/FALSE
|
|
//
|
|
WORD APIENTRY IsCDRomDrive(INT iDrive)
|
|
{
|
|
if (rgiDriveType[iDrive] == DRIVE_CDROM)
|
|
return(TRUE);
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
// this is called for every drive at init time so it must
|
|
// be sure to not trigget things like the phantom B: drive support
|
|
//
|
|
// iDrive is a zero based drive number (0 = A, 1 = B)
|
|
|
|
WORD APIENTRY IsNetDrive(INT iDrive)
|
|
{
|
|
INT err;
|
|
CHAR szDrive[3];
|
|
CHAR szConn[64]; // this really should be WNBD_MAX_LENGTH
|
|
// but this change would have to be many everywhere
|
|
|
|
szDrive[0] = (CHAR)(iDrive+'A');
|
|
szDrive[1] = ':';
|
|
szDrive[2] = (CHAR)0;
|
|
|
|
if (IsCDRomDrive(iDrive)) // this is bogus... move this out
|
|
return 0;
|
|
|
|
err = WFGetConnection(szDrive, szConn, TRUE);
|
|
|
|
if (err == WN_SUCCESS)
|
|
return 1;
|
|
|
|
if (err == WN_CONNECTION_CLOSED || err == WN_DEVICE_ERROR)
|
|
return 2;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
BOOL APIENTRY IsRemovableDrive(register INT iDrive)
|
|
{
|
|
return DriveType(iDrive) == DRIVE_REMOVABLE;
|
|
}
|
|
|
|
|
|
BOOL APIENTRY IsRemoteDrive(register INT iDrive)
|
|
{
|
|
return DriveType(iDrive) == DRIVE_REMOTE;
|
|
}
|
|
|
|
|
|
// iDrive zero based drive number (A = 0)
|
|
|
|
BOOL APIENTRY IsRamDrive(INT iDrive)
|
|
{
|
|
return DriveType(iDrive) == DRIVE_RAMDISK;
|
|
}
|
|
|
|
|
|
// get interesting stuff about a drive
|
|
//
|
|
// zero based drive numbers (0 = A, 1 = B)
|
|
//
|
|
|
|
DWORD APIENTRY GetClusterInfo(WORD drive)
|
|
{
|
|
#ifdef ORGCODE
|
|
DevPB dpbDiskParms; /* Device Parameters */
|
|
|
|
// try the fast way...
|
|
|
|
memset(&dpbDiskParms, 0, sizeof(dpbDiskParms));
|
|
|
|
if (!DeviceParameters(drive, &dpbDiskParms, IOCTL_GET_DPB))
|
|
return MAKELONG((WORD)dpbDiskParms.BPB.secPerClus, dpbDiskParms.BPB.cbSec);
|
|
|
|
// very slow way...
|
|
|
|
_asm {
|
|
mov ah,36h
|
|
mov dx,drive
|
|
inc dx ; make it 1 based.
|
|
int 21h
|
|
inc ax ; if Error, ax = -1, else, ax = sectors/cluster
|
|
jz GCSdone ; Yup, Error. Return zero.
|
|
dec ax ; Get back sectors/cluster.
|
|
mov dx, cx ; cx = bytes/sector
|
|
GCSdone:
|
|
}
|
|
#else
|
|
UNREFERENCED_PARAMETER(drive);
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
BOOL APIENTRY IsValidDisk(INT iDrive)
|
|
{
|
|
if (apVolInfo[iDrive] == NULL)
|
|
FillVolumeInfo(iDrive);
|
|
|
|
return(apVolInfo[iDrive] != NULL);
|
|
}
|
|
|
|
|
|
VOID APIENTRY GetVolShare(WORD wDrive, LPSTR szVolShare)
|
|
{
|
|
CHAR szDrive[5];
|
|
|
|
szVolShare[0] = TEXT('\0');
|
|
|
|
#ifdef OLD
|
|
if (!IsCDRomDrive(wDrive))
|
|
{
|
|
|
|
szDrive[0] = (CHAR)('A'+ wDrive);
|
|
szDrive[1] = ':';
|
|
szDrive[2] = 0;
|
|
if (WFGetConnection(szDrive,szVolShare,FALSE) != WN_SUCCESS) {
|
|
GetVolumeLabel(wDrive, szVolShare, TRUE);
|
|
OemToAnsi(szVolShare, szVolShare);
|
|
}
|
|
else
|
|
lstrcpy(szVolShare,"CD-ROM");
|
|
#else
|
|
lstrcpy(szVolShare, "Objects");
|
|
#endif
|
|
}
|
|
|
|
|
|
#ifdef LFN
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* IsLFNSelected() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
BOOL APIENTRY IsLFNSelected()
|
|
{
|
|
HWND hwndActive;
|
|
BOOL fDir;
|
|
LPSTR p;
|
|
|
|
hwndActive = (HWND)SendMessage(hwndMDIClient, WM_MDIGETACTIVE, 0, 0L);
|
|
|
|
p = (LPSTR)SendMessage(hwndActive, FS_GETSELECTION, 2, (LONG)&fDir);
|
|
if (p) {
|
|
LocalFree((HANDLE)p);
|
|
}
|
|
|
|
return(fDir);
|
|
}
|
|
|
|
#endif
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* GetSelection() - */
|
|
|
|
// caller must free lpstr returned.
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
LPSTR APIENTRY GetSelection(INT iSelType)
|
|
{
|
|
HWND hwndActive;
|
|
|
|
hwndActive = (HWND)SendMessage(hwndMDIClient, WM_MDIGETACTIVE, 0, 0L);
|
|
|
|
return (LPSTR)SendMessage(hwndActive,FS_GETSELECTION, (WPARAM)iSelType, 0L);
|
|
}
|
|
|
|
|
|
//
|
|
// in:
|
|
// pFrom pointer that is used as start of selection search.
|
|
// on subsequent calls pass in the previous non NULL
|
|
// return value
|
|
//
|
|
// out:
|
|
// pTo buffer that receives the next file in the list
|
|
// for non NULL return
|
|
//
|
|
// returns:
|
|
// NULL if no more files in this list (szFile) is undefined
|
|
// pointer to be passed to subsequent calls to this function
|
|
// to enumerate thorough the file list
|
|
//
|
|
|
|
LPSTR APIENTRY GetNextFile(LPSTR pFrom, LPSTR pTo, INT cbMax)
|
|
{
|
|
INT i;
|
|
|
|
ENTER("GetNextFile");
|
|
PRINT(BF_PARMTRACE, "IN: pFrom=%s", pFrom);
|
|
|
|
if (!pFrom)
|
|
return NULL;
|
|
|
|
/* Skip over leading spaces and commas. */
|
|
while (*pFrom && (*pFrom == ' ' || *pFrom == ','))
|
|
#ifdef DBCS
|
|
pFrom = (LPSTR)AnsiNext(pFrom);
|
|
#else
|
|
pFrom++;
|
|
#endif
|
|
|
|
if (!*pFrom)
|
|
return(NULL);
|
|
|
|
if (*pFrom == '\"') {
|
|
#ifdef DBCS
|
|
pFrom = (LPSTR)AnsiNext(pFrom);
|
|
#else
|
|
pFrom++;
|
|
#endif
|
|
|
|
/* Find the next quote */
|
|
for (i=0; *pFrom && *pFrom != '\"';)
|
|
{
|
|
if (*pFrom == '^')
|
|
{
|
|
#ifdef DBCS
|
|
pFrom = (LPSTR)AnsiNext(pFrom)
|
|
#else
|
|
++pFrom;
|
|
#endif
|
|
if (!*pFrom)
|
|
break;
|
|
}
|
|
|
|
if (i < cbMax - 1)
|
|
{
|
|
#ifdef DBCS
|
|
i++;
|
|
if (IsDBCSLeadByte(*pTo++ = *pFrom++))
|
|
#endif
|
|
{
|
|
i++;
|
|
*pTo++ = *pFrom++;
|
|
}
|
|
}
|
|
}
|
|
#ifdef DBCS
|
|
pFrom = (LPSTR)AnsiNext(pFrom);
|
|
#else
|
|
pFrom++;
|
|
#endif
|
|
} else {
|
|
/* Find the next space or comma. */
|
|
for (i=0; *pFrom && *pFrom != ' ' && *pFrom != ',';) {
|
|
if (*pFrom == '^') {
|
|
#ifdef DBCS
|
|
pFrom = (LPSTR)AnsiNext(pFrom)
|
|
#else
|
|
++pFrom;
|
|
#endif
|
|
if (!*pFrom)
|
|
break;
|
|
}
|
|
|
|
if (i < cbMax - 1) {
|
|
#ifdef DBCS
|
|
i++;
|
|
if (IsDBCSLeadByte(*pTo++ = *pFrom++))
|
|
#endif
|
|
{
|
|
i++;
|
|
*pTo++ = *pFrom++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
*pTo = TEXT('\0');
|
|
|
|
PRINT(BF_PARMTRACE, pTo ? "OUT: pTo=%s" : "OUT: pTo=NULL", pTo);
|
|
LEAVE("GetNextFile");
|
|
|
|
return(pFrom);
|
|
}
|
|
|
|
|
|
// sets the DOS current directory based on the currently active window
|
|
|
|
VOID APIENTRY SetWindowDirectory()
|
|
{
|
|
CHAR szTemp[MAXPATHLEN];
|
|
|
|
GetSelectedDirectory(0, szTemp);
|
|
FixAnsiPathForDos(szTemp);
|
|
SheChangeDir(szTemp);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* SetDlgDirectory() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/* Sets the IDD_DIR field of 'hDlg' to whatever the active window says is the
|
|
* active directory.
|
|
*
|
|
* this does not really change the DOS current directory
|
|
*/
|
|
|
|
VOID APIENTRY SetDlgDirectory(HWND hDlg, PSTR pszPath)
|
|
{
|
|
HDC hDC;
|
|
INT dx;
|
|
RECT rc;
|
|
HWND hDlgItem;
|
|
HANDLE hFont;
|
|
CHAR szPath[MAXPATHLEN+5];
|
|
CHAR szTemp[MAXPATHLEN+20];
|
|
|
|
ENTER("SetDlgDirectory");
|
|
|
|
if (pszPath)
|
|
lstrcpy(szPath, pszPath);
|
|
else
|
|
GetSelectedDirectory(0, szPath);
|
|
|
|
/* Make sure that the current directory fits inside the static text field. */
|
|
hDlgItem = GetDlgItem(hDlg, IDD_DIR);
|
|
GetClientRect(hDlgItem, &rc);
|
|
|
|
if (LoadString(hAppInstance, IDS_CURDIRIS, szMessage, sizeof(szMessage))) {
|
|
hDC = GetDC(hDlg);
|
|
hFont = (HANDLE)SendMessage(hDlgItem, WM_GETFONT, 0, 0L);
|
|
if (hFont = SelectObject(hDC, hFont)) {
|
|
MGetTextExtent(hDC, szMessage, lstrlen(szMessage), &dx, NULL);
|
|
CompactPath(hDC, szPath, (WORD)(rc.right-rc.left-dx));
|
|
}
|
|
SelectObject(hDC, hFont);
|
|
ReleaseDC(hDlg, hDC);
|
|
wsprintf(szTemp, szMessage, (LPSTR)szPath);
|
|
SetDlgItemText(hDlg, IDD_DIR, szTemp);
|
|
}
|
|
|
|
LEAVE("SetDlgDirectory");
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* WritePrivateProfileBool() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
VOID APIENTRY WritePrivateProfileBool(LPSTR szKey, BOOL bParam)
|
|
{
|
|
CHAR szBool[6];
|
|
|
|
wsprintf(szBool, "%d", bParam);
|
|
WritePrivateProfileString(szSettings, szKey, szBool, szTheINIFile);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* WFQueryAbort() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
BOOL APIENTRY WFQueryAbort()
|
|
|
|
{
|
|
MSG msg;
|
|
|
|
while (PeekMessage(&msg, NULL, 0, 0, TRUE))
|
|
{
|
|
if (!IsDialogMessage(hdlgProgress, &msg))
|
|
DispatchMessage(&msg);
|
|
}
|
|
return(bUserAbort);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* IsWild() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/* Returns TRUE iff the path contains * or ? */
|
|
|
|
BOOL APIENTRY IsWild(LPSTR lpszPath)
|
|
|
|
{
|
|
while (*lpszPath)
|
|
{
|
|
if (*lpszPath == '?' || *lpszPath == '*')
|
|
return(TRUE);
|
|
#ifdef DBCS
|
|
lpszPath = AnsiNext(lpszPath);
|
|
#else
|
|
lpszPath++;
|
|
#endif
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* CheckSlashies() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/* Replaces frontslashes (evil) with backslashes (good). */
|
|
|
|
VOID APIENTRY CheckSlashies(LPSTR lpT)
|
|
{
|
|
while (*lpT)
|
|
{
|
|
if (*lpT == '/')
|
|
*lpT = '\\';
|
|
#ifdef DBCS
|
|
lpT = AnsiNext(lpT);
|
|
#else
|
|
lpT++;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* AddBackslash() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/* Ensures that a path ends with a backslash. */
|
|
|
|
VOID APIENTRY AddBackslash(LPSTR lpszPath)
|
|
{
|
|
ENTER("AddBackslash");
|
|
PRINT(BF_PARMTRACE, "IN: lpszPath=%s", lpszPath);
|
|
|
|
if (*AnsiPrev(lpszPath,lpszPath+lstrlen(lpszPath)) != '\\')
|
|
lstrcat(lpszPath, "\\");
|
|
|
|
PRINT(BF_PARMTRACE, "OUT: lpszPath=%s", lpszPath);
|
|
|
|
LEAVE("AddBackslash");
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* StripBackslash() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/* Removes a trailing backslash from a proper directory name UNLESS it is
|
|
* the root directory. Assumes a fully qualified directory path.
|
|
*/
|
|
|
|
VOID APIENTRY StripBackslash(LPSTR lpszPath)
|
|
{
|
|
register WORD len;
|
|
|
|
#ifdef DBCS
|
|
len = lstrlen(lpszPath) - (IsDBCSLeadByte(*AnsiPrev(lpszPath,lpszPath+lstrlen(lpszPath))) ? 2 : 1);
|
|
#else
|
|
len = (WORD)(lstrlen(lpszPath) - 1);
|
|
#endif
|
|
if ((len == 2) || (lpszPath[len] != '\\'))
|
|
return;
|
|
|
|
lpszPath[len] = TEXT('\0');
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* StripFilespec() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/* Remove the filespec portion from a path (including the backslash). */
|
|
|
|
VOID APIENTRY StripFilespec(LPSTR lpszPath)
|
|
{
|
|
LPSTR p;
|
|
|
|
#ifdef DBCS
|
|
p = lpszPath + lstrlen(lpszPath);
|
|
while ((*p != '\\') && (*p != ':') && (p != lpszPath))
|
|
p = AnsiPrev(lpszPath, p);
|
|
#else
|
|
p = lpszPath + lstrlen(lpszPath);
|
|
while ((*p != '\\') && (*p != ':') && (p != lpszPath))
|
|
p--;
|
|
#endif
|
|
|
|
if (*p == ':')
|
|
p++;
|
|
|
|
/* Don't strip backslash from root directory entry. */
|
|
if (p != lpszPath)
|
|
{
|
|
if ((*p == '\\') && (*(p-1) == ':'))
|
|
p++;
|
|
}
|
|
else
|
|
p++;
|
|
|
|
*p = TEXT('\0');
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* StripPath() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/* Extract only the filespec portion from a path. */
|
|
|
|
VOID APIENTRY StripPath(LPSTR lpszPath)
|
|
{
|
|
LPSTR p;
|
|
|
|
ENTER("StripPath");
|
|
PRINT(BF_PARMTRACE, "IN: lpszPath=%s", lpszPath);
|
|
|
|
p = lpszPath + lstrlen(lpszPath);
|
|
#ifdef DBCS
|
|
while ((*p != '\\') && (*p != ':') && (p != lpszPath))
|
|
p = AnsiPrev(lpszPath, p);
|
|
#else
|
|
while ((*p != '\\') && (*p != ':') && (p != lpszPath))
|
|
p--;
|
|
#endif
|
|
|
|
if (p != lpszPath || *p == '\\')
|
|
p++;
|
|
|
|
if (p != lpszPath)
|
|
lstrcpy(lpszPath, p);
|
|
|
|
PRINT(BF_PARMTRACE, "OUT: lpszPath=%s", lpszPath);
|
|
LEAVE("StripPath");
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* GetExtension() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/* Returns the extension part of a filename. */
|
|
|
|
LPSTR APIENTRY GetExtension(LPSTR pszFile)
|
|
{
|
|
PSTR p, pSave = NULL;
|
|
|
|
p = pszFile;
|
|
while (*p)
|
|
{
|
|
if (*p == '.')
|
|
pSave = p;
|
|
#ifdef DBCS
|
|
p = (LPSTR)AnsiNext(p);
|
|
#else
|
|
p++;
|
|
#endif
|
|
}
|
|
|
|
if (!pSave)
|
|
return(p);
|
|
|
|
#ifdef DBCS
|
|
return (LPSTR)AnsiNext(pSave);
|
|
#else
|
|
return pSave+1;
|
|
#endif
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* FindExtensionInList() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/* Returns TRUE if 'lpszExt' is somewhere in 'pszList'. */
|
|
|
|
BOOL APIENTRY FindExtensionInList(LPSTR pszExt, LPSTR pszList)
|
|
{
|
|
LPSTR p2;
|
|
CHAR ch;
|
|
|
|
while (*pszList)
|
|
{
|
|
/* Move to the next item in the list. */
|
|
while ((*pszList) && (*pszList == ' '))
|
|
#ifdef DBCS
|
|
pszList = (LPSTR)AnsiNext(pszList);
|
|
#else
|
|
pszList++;
|
|
#endif
|
|
|
|
if (!*pszList)
|
|
break;
|
|
|
|
/* NULL-terminate this item. */
|
|
#ifdef DBCS
|
|
p2 = (LPSTR)AnsiNext(pszList);
|
|
#else
|
|
p2 = pszList+1;
|
|
#endif
|
|
while ((*p2) && (*p2 != ' '))
|
|
#ifdef DBCS
|
|
p2 = (LPSTR)AnsiNext(p2);
|
|
#else
|
|
p2++;
|
|
#endif
|
|
ch = *p2;
|
|
*p2 = TEXT('\0');
|
|
if (!lstrcmpi(pszExt, pszList))
|
|
{
|
|
*p2 = ch;
|
|
return(TRUE);
|
|
}
|
|
*p2 = ch;
|
|
pszList = p2;
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* MyMessageBox() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
INT APIENTRY MyMessageBox(HWND hWnd, WORD idTitle, WORD idMessage, WORD wStyle)
|
|
{
|
|
CHAR szTemp[MAXMESSAGELEN];
|
|
HWND hwndT;
|
|
|
|
LoadString(hAppInstance, idTitle, szTitle, sizeof(szTitle));
|
|
|
|
if (idMessage < 32)
|
|
{
|
|
LoadString(hAppInstance, IDS_UNKNOWNMSG, szTemp, sizeof(szTemp));
|
|
wsprintf(szMessage, szTemp, idMessage);
|
|
}
|
|
else
|
|
LoadString(hAppInstance, idMessage, szMessage, sizeof(szMessage));
|
|
|
|
if (hWnd)
|
|
hwndT = GetLastActivePopup(hWnd);
|
|
else
|
|
hwndT = hWnd;
|
|
|
|
return MessageBox(hwndT, szMessage, szTitle, wStyle | MB_TASKMODAL);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* ExecProgram() - */
|
|
/* */
|
|
/* all strings are OEM */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/* Returns 0 for success. Otherwise returns a IDS_ string code. */
|
|
|
|
WORD APIENTRY ExecProgram(LPSTR lpPath, LPSTR lpParms, LPSTR lpDir, BOOL bLoadIt)
|
|
{
|
|
WORD ret;
|
|
INT iCurCount;
|
|
INT i;
|
|
HCURSOR hCursor;
|
|
|
|
ENTER("ExecProgram");
|
|
|
|
ret = 0;
|
|
|
|
hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
iCurCount = ShowCursor(TRUE) - 1;
|
|
|
|
/* open the object
|
|
*/
|
|
|
|
if (lpPath)
|
|
OemToAnsi(lpPath, lpPath);
|
|
if (lpParms)
|
|
OemToAnsi(lpParms, lpParms);
|
|
if (lpDir)
|
|
OemToAnsi(lpDir, lpDir);
|
|
|
|
// Shell Execute takes ansi string.
|
|
//
|
|
// BUGBUG: WIN31 and NT have different RealShellExecute params....
|
|
ret = (WORD)RealShellExecute(hwndFrame, NULL, lpPath, lpParms, lpDir, NULL, NULL, NULL, (WORD)(bLoadIt ? SW_SHOWMINNOACTIVE : SW_SHOWNORMAL), NULL);
|
|
|
|
DosResetDTAAddress(); // undo any bad things COMMDLG did
|
|
|
|
if (lpPath)
|
|
AnsiToOem(lpPath, lpPath);
|
|
if (lpParms)
|
|
AnsiToOem(lpParms, lpParms);
|
|
if (lpDir)
|
|
AnsiToOem(lpDir, lpDir);
|
|
|
|
switch (ret) {
|
|
case 0:
|
|
case 8:
|
|
ret = IDS_NOMEMORYMSG;
|
|
break;
|
|
|
|
case 2:
|
|
ret = IDS_FILENOTFOUNDMSG;
|
|
break;
|
|
|
|
case 3:
|
|
case 5: // access denied
|
|
ret = IDS_BADPATHMSG;
|
|
break;
|
|
|
|
case 4:
|
|
ret = IDS_MANYOPENFILESMSG;
|
|
break;
|
|
|
|
case 10:
|
|
ret = IDS_NEWWINDOWSMSG;
|
|
break;
|
|
|
|
case 12:
|
|
ret = IDS_OS2APPMSG;
|
|
break;
|
|
|
|
case 15:
|
|
/* KERNEL has already put up a messagebox for this one. */
|
|
ret = 0;
|
|
break;
|
|
|
|
case 16:
|
|
ret = IDS_MULTIPLEDSMSG;
|
|
break;
|
|
|
|
case 18:
|
|
ret = IDS_PMODEONLYMSG;
|
|
break;
|
|
|
|
case 19:
|
|
ret = IDS_COMPRESSEDEXE;
|
|
break;
|
|
|
|
case 20:
|
|
ret = IDS_INVALIDDLL;
|
|
break;
|
|
|
|
case SE_ERR_SHARE:
|
|
ret = IDS_SHAREERROR;
|
|
break;
|
|
|
|
case SE_ERR_ASSOCINCOMPLETE:
|
|
ret = IDS_ASSOCINCOMPLETE;
|
|
break;
|
|
|
|
case SE_ERR_DDETIMEOUT:
|
|
case SE_ERR_DDEFAIL:
|
|
case SE_ERR_DDEBUSY:
|
|
ret = IDS_DDEFAIL;
|
|
break;
|
|
|
|
case SE_ERR_NOASSOC:
|
|
ret = IDS_NOASSOCMSG;
|
|
break;
|
|
|
|
default:
|
|
if (ret < 32)
|
|
goto EPExit;
|
|
|
|
if (bMinOnRun && !bLoadIt)
|
|
ShowWindow(hwndFrame, SW_SHOWMINNOACTIVE);
|
|
ret = 0;
|
|
}
|
|
|
|
EPExit:
|
|
i = ShowCursor(FALSE);
|
|
|
|
#if 0
|
|
|
|
/* Make sure that the cursor count is still balanced. */
|
|
if (i != iCurCount)
|
|
ShowCursor(TRUE);
|
|
#endif
|
|
|
|
SetCursor(hCursor);
|
|
|
|
PRINT(BF_PARMTRACE, "OUT: ret=%ud", ret);
|
|
LEAVE("ExecProgram");
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* IsProgramFile() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/* Returns TRUE is the Path points to a file which has one of the extentions
|
|
* listed in the "Programs=" portions of WIN.INI.
|
|
*/
|
|
|
|
BOOL APIENTRY IsProgramFile(LPSTR lpszPath)
|
|
{
|
|
LPSTR szExt;
|
|
CHAR szTemp[MAXPATHLEN];
|
|
|
|
/* Move the string into our own DS. */
|
|
lstrcpy(szTemp, lpszPath);
|
|
|
|
/* Get the file's extension. */
|
|
StripPath(szTemp);
|
|
szExt = GetExtension(szTemp);
|
|
|
|
if (!*szExt)
|
|
{
|
|
/* The specified path didn't have an extention. It can't be a program. */
|
|
return(FALSE);
|
|
}
|
|
|
|
return FindExtensionInList(szExt, szPrograms);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* IsDocument() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/* Returns TRUE is the Path points to a file which has one of the extentions
|
|
* listed in the "Documents=" portions of WIN.INI or one which has an Association.
|
|
*/
|
|
|
|
BOOL APIENTRY IsDocument(LPSTR lpszPath)
|
|
{
|
|
LPSTR szExt;
|
|
CHAR szTemp[MAXPATHLEN];
|
|
|
|
/* Move the string into our own DS. */
|
|
lstrcpy(szTemp, lpszPath);
|
|
|
|
/* Get the file's extension. */
|
|
StripPath(szTemp);
|
|
szExt = GetExtension(szTemp);
|
|
|
|
if (!*szExt)
|
|
{
|
|
/* The specified path didn't have an extention. It can't be a program. */
|
|
return(FALSE);
|
|
}
|
|
|
|
return FindExtensionInList(szExt, szDocuments);
|
|
}
|