UTILITY.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:28k
源码类别:
Windows编程
开发平台:
Visual C++
- /*
- * UTILITY.C
- *
- * Utility routines for functions inside OLESTD.LIB
- *
- * General:
- * ----------------------
- * HourGlassOn Displays the hourglass
- * HourGlassOff Hides the hourglass
- *
- * Misc Tools:
- * ----------------------
- * Browse Displays the "File..." or "Browse..." dialog.
- * ReplaceCharWithNull Used to form filter strings for Browse.
- * ErrorWithFile Creates an error message with embedded filename
- * OpenFileError Give error message for OpenFile error return
- * ChopText Chop a file path to fit within a specified width
- * DoesFileExist Checks if file is valid
- *
- * Registration Database:
- * ----------------------
- * HIconFromClass Extracts the first icon in a class's server path
- * FServerFromClass Retrieves the server path for a class name (fast)
- * UClassFromDescription Finds the classname given a description (slow)
- * UDescriptionFromClass Retrieves the description for a class name (fast)
- * FGetVerb Retrieves a specific verb for a class (fast)
- *
- *
- * Copyright (c)1992-1996 Microsoft Corporation, All Right Reserved
- */
- #define STRICT 1
- #include "olestd.h"
- #include <stdlib.h>
- #include <commdlg.h>
- #include <memory.h>
- #include <cderr.h>
- #include "common.h"
- #include "utility.h"
- #ifdef WIN32
- /* 1/23/94 - define LINK_COMMDLG to avoid LoadLibrary("commdlg.dll") */
- #define LINK_COMMDLG
- #endif
- OLEDBGDATA
- /*
- * HourGlassOn
- *
- * Purpose:
- * Shows the hourglass cursor returning the last cursor in use.
- *
- * Parameters:
- * None
- *
- * Return Value:
- * HCURSOR Cursor in use prior to showing the hourglass.
- */
- HCURSOR WINAPI HourGlassOn(void)
- {
- HCURSOR hCur;
- hCur=SetCursor(LoadCursor(NULL, IDC_WAIT));
- ShowCursor(TRUE);
- return hCur;
- }
- /*
- * HourGlassOff
- *
- * Purpose:
- * Turns off the hourglass restoring it to a previous cursor.
- *
- * Parameters:
- * hCur HCURSOR as returned from HourGlassOn
- *
- * Return Value:
- * None
- */
- void WINAPI HourGlassOff(HCURSOR hCur)
- {
- ShowCursor(FALSE);
- SetCursor(hCur);
- return;
- }
- /*
- * Browse
- *
- * Purpose:
- * Displays the standard GetOpenFileName dialog with the title of
- * "Browse." The types listed in this dialog are controlled through
- * iFilterString. If it's zero, then the types are filled with "*.*"
- * Otherwise that string is loaded from resources and used.
- *
- * Parameters:
- * hWndOwner HWND owning the dialog
- * lpszFile LPSTR specifying the initial file and the buffer in
- * which to return the selected file. If there is no
- * initial file the first character of this string should
- * be NULL.
- * lpszInitialDir LPSTR specifying the initial directory. If none is to
- * set (ie, the cwd should be used), then this parameter
- * should be NULL.
- * cchFile UINT length of pszFile
- * iFilterString UINT index into the stringtable for the filter string.
- * dwOfnFlags DWORD flags to OR with OFN_HIDEREADONLY
- *
- * Return Value:
- * BOOL TRUE if the user selected a file and pressed OK.
- * FALSE otherwise, such as on pressing Cancel.
- */
- BOOL WINAPI Browse(HWND hWndOwner, LPSTR lpszFile, LPSTR lpszInitialDir, UINT cchFile, UINT iFilterString, DWORD dwOfnFlags)
- {
- UINT cch;
- char szFilters[256];
- OPENFILENAME ofn;
- BOOL fStatus;
- DWORD dwError;
- char szDlgTitle[128]; // that should be big enough
- #if !defined( LINK_COMMDLG )
- HINSTANCE hinstCommDlg = NULL;
- typedef BOOL (WINAPI* LPFNGETOPENFILENAME) (OPENFILENAME FAR*);
- LPFNGETOPENFILENAME lpfnGetOpenFileName;
- typedef DWORD (WINAPI* LPFNCOMMDLGEXTENDEDERROR) (void);
- LPFNCOMMDLGEXTENDEDERROR lpfnCommDlgExtendedError;
- #endif
- if (NULL==lpszFile || 0==cchFile)
- return FALSE;
- /*
- * REVIEW: Exact contents of the filter combobox is TBD. One idea
- * is to take all the extensions in the RegDB and place them in here
- * with the descriptive class name associate with them. This has the
- * extra step of finding all extensions of the same class handler and
- * building one extension string for all of them. Can get messy quick.
- * UI demo has only *.* which we do for now.
- */
- if (0!=iFilterString)
- cch=LoadString(ghInst, iFilterString, /*(LPSTR)*/szFilters, sizeof(szFilters));
- else
- {
- szFilters[0]=0;
- cch=1;
- }
- if (0==cch)
- return FALSE;
- ReplaceCharWithNull(szFilters, szFilters[cch-1]);
- //Prior string must also be initialized, if there is one.
- _fmemset((LPOPENFILENAME)&ofn, 0, sizeof(ofn));
- ofn.lStructSize =sizeof(ofn);
- ofn.hwndOwner =hWndOwner;
- ofn.lpstrFile =lpszFile;
- ofn.nMaxFile =cchFile;
- ofn.lpstrFilter =/*(LPSTR)*/szFilters;
- ofn.nFilterIndex=1;
- if (LoadString(ghInst, (UINT)IDS_BROWSE, /*(LPSTR)*/szDlgTitle, sizeof(szDlgTitle)))
- ofn.lpstrTitle =/*(LPSTR)*/szDlgTitle;
- ofn.hInstance = ghInst;
- ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILEOPEN);
- if (NULL != lpszInitialDir)
- ofn.lpstrInitialDir = lpszInitialDir;
- ofn.Flags= OFN_HIDEREADONLY | OFN_ENABLETEMPLATE | (dwOfnFlags) ;
- #if !defined( LINK_COMMDLG )
- // Load the COMMDLG.DLL library module
- hinstCommDlg = LoadLibrary("COMMDLG.DLL");
- if (hinstCommDlg <= HINSTANCE_ERROR) /* load failed */
- return FALSE;
- // Retrieve the address of required functions
- lpfnGetOpenFileName = (LPFNGETOPENFILENAME)
- GetProcAddress(hinstCommDlg, "GetOpenFileName");
- lpfnCommDlgExtendedError = (LPFNCOMMDLGEXTENDEDERROR)
- GetProcAddress(hinstCommDlg, "CommDlgExtendedError");
- if (lpfnGetOpenFileName == NULL || lpfnCommDlgExtendedError == NULL)
- {
- FreeLibrary(hinstCommDlg);
- return FALSE;
- }
- //On success, copy the chosen filename to the static display
- fStatus = (*lpfnGetOpenFileName) ((LPOPENFILENAME)&ofn);
- dwError = (*lpfnCommDlgExtendedError)();
- FreeLibrary(hinstCommDlg);
- return fStatus;
- #else
- //On success, copy the chosen filename to the static display
- fStatus = GetOpenFileName((LPOPENFILENAME)&ofn);
- dwError = CommDlgExtendedError();
- return fStatus;
- #endif
- }
- /*
- * ReplaceCharWithNull
- *
- * Purpose:
- * Walks a null-terminated string and replaces a given character
- * with a zero. Used to turn a single string for file open/save
- * filters into the appropriate filter string as required by the
- * common dialog API.
- *
- * Parameters:
- * psz LPSTR to the string to process.
- * ch int character to replace.
- *
- * Return Value:
- * int Number of characters replaced. -1 if psz is NULL.
- */
- int WINAPI ReplaceCharWithNull(LPSTR psz, int ch)
- {
- int cChanged=-1;
- if (NULL!=psz)
- {
- while (0!=*psz)
- {
- if (ch==*psz)
- {
- *psz=0;
- cChanged++;
- }
- psz++;
- }
- }
- return cChanged;
- }
- /*
- * ErrorWithFile
- *
- * Purpose:
- * Displays a message box built from a stringtable string containing
- * one %s as a placeholder for a filename and from a string of the
- * filename to place there.
- *
- * Parameters:
- * hWnd HWND owning the message box. The caption of this
- * window is the caption of the message box.
- * hInst HINSTANCE from which to draw the idsErr string.
- * idsErr UINT identifier of a stringtable string containing
- * the error message with a %s.
- * lpszFile LPSTR to the filename to include in the message.
- * uFlags UINT flags to pass to MessageBox, like MB_OK.
- *
- * Return Value:
- * int Return value from MessageBox.
- */
- int WINAPI ErrorWithFile(HWND hWnd, HINSTANCE hInst, UINT idsErr
- , LPSTR pszFile, UINT uFlags)
- {
- int iRet=0;
- HANDLE hMem;
- const UINT cb=(2*OLEUI_CCHPATHMAX);
- LPSTR psz1, psz2, psz3;
- if (NULL==hInst || NULL==pszFile)
- return iRet;
- //Allocate three 2*OLEUI_CCHPATHMAX byte work buffers
- hMem=GlobalAlloc(GHND, (DWORD)(3*cb));
- if (NULL==hMem)
- return iRet;
- psz1=GlobalLock(hMem);
- psz2=psz1+cb;
- psz3=psz2+cb;
- if (0!=LoadString(hInst, idsErr, psz1, cb))
- {
- wsprintf(psz2, psz1, pszFile);
- //Steal the caption of the dialog
- GetWindowText(hWnd, psz3, cb);
- iRet=MessageBox(hWnd, psz2, psz3, uFlags);
- }
- GlobalUnlock(hMem);
- GlobalFree(hMem);
- return iRet;
- }
- /*
- * HIconFromClass
- *
- * Purpose:
- * Given an object class name, finds an associated executable in the
- * registration database and extracts the first icon from that
- * executable. If none is available or the class has no associated
- * executable, this function returns NULL.
- *
- * Parameters:
- * pszClass LPSTR giving the object class to look up.
- *
- * Return Value:
- * HICON Handle to the extracted icon if there is a module
- * associated to pszClass. NULL on failure to either
- * find the executable or extract and icon.
- */
- HICON WINAPI HIconFromClass(LPSTR pszClass)
- {
- HICON hIcon;
- char szEXE[OLEUI_CCHPATHMAX];
- UINT Index;
- CLSID clsid;
- OLECHAR szUniStr[256];
- if (NULL==pszClass)
- return NULL;
- A2W (pszClass, szUniStr, 256);
- CLSIDFromString(szUniStr, &clsid);
- if (!FIconFileFromClass((REFCLSID)&clsid, szEXE, sizeof(szEXE), &Index))
- return NULL;
- hIcon=ExtractIcon(ghInst, szEXE, Index);
- if ((HICON)32 > hIcon)
- hIcon=NULL;
- return hIcon;
- }
- /*
- * FServerFromClass
- *
- * Purpose:
- * Looks up the classname in the registration database and retrieves
- * the name under CLSID[Local|InProc]Server.
- *
- * Parameters:
- * pszClass LPSTR to the classname to look up.
- * pszEXE LPSTR at which to store the server name
- * cch UINT size of pszEXE
- *
- * Return Value:
- * BOOL TRUE if one or more characters were loaded into pszEXE.
- * FALSE otherwise.
- */
- BOOL WINAPI FServerFromClass(LPSTR pszClass, LPSTR pszEXE, UINT cch)
- {
- DWORD dw;
- LONG lRet;
- HKEY hKey;
- if (NULL==pszClass || NULL==pszEXE || 0==cch)
- return FALSE;
- /*
- * We have to go walking in the registration database under the
- * classname, so we first open the classname key and then check
- * under "\LocalServer" to get the .EXE.
- */
- //Open up the class key
- lRet=RegOpenKey(HKEY_CLASSES_ROOT, pszClass, &hKey);
- if ((LONG)ERROR_SUCCESS!=lRet)
- return FALSE;
- //Get the executable path.
- dw=(DWORD)cch;
- #ifdef WIN32
- lRet=RegQueryValue(hKey, "LocalServer32", pszEXE, &dw);
- #else
- lRet=RegQueryValue(hKey, "LocalServer", pszEXE, &dw);
- #endif
- if ((LONG)ERROR_SUCCESS!=lRet)
- {
- //Try InprocServer
- #ifdef WIN32
- lRet=RegQueryValue(hKey, "InProcServer32", pszEXE, &dw);
- #else
- lRet=RegQueryValue(hKey, "InProcServer32", pszEXE, &dw);
- #endif
- }
- RegCloseKey(hKey);
- return ((ERROR_SUCCESS == lRet) && (dw > 0));
- }
- /*
- * UClassFromDescription
- *
- * Purpose:
- * Looks up the actual OLE class name in the registration database
- * for the given descriptive name chosen from a listbox.
- *
- * Parameters:
- * psz LPSTR to the descriptive name.
- * pszClass LPSTR in which to store the class name.
- * cb UINT maximum length of pszClass.
- *
- * Return Value:
- * UINT Number of characters copied to pszClass. 0 on failure.
- */
- UINT WINAPI UClassFromDescription(LPSTR psz, LPSTR pszClass, UINT cb)
- {
- DWORD dw;
- HKEY hKey;
- char szClass[OLEUI_CCHKEYMAX];
- LONG lRet;
- UINT i;
- //Open up the root key.
- lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
- if ((LONG)ERROR_SUCCESS!=lRet)
- return 0;
- i=0;
- lRet=RegEnumKey(hKey, i++, szClass, OLEUI_CCHKEYMAX);
- //Walk the available keys
- while ((LONG)ERROR_SUCCESS==lRet)
- {
- dw=(DWORD)cb;
- lRet=RegQueryValue(hKey, szClass, pszClass, &dw);
- //Check if the description matches the one just enumerated
- if ((LONG)ERROR_SUCCESS==lRet)
- {
- if (!lstrcmp(pszClass, psz))
- break;
- }
- //Continue with the next key.
- lRet=RegEnumKey(hKey, i++, szClass, OLEUI_CCHKEYMAX);
- }
- //If we found it, copy to the return buffer
- if ((LONG)ERROR_SUCCESS==lRet)
- lstrcpy(pszClass, szClass);
- else
- dw=0L;
- RegCloseKey(hKey);
- return (UINT)dw;
- }
- /*
- * UDescriptionFromClass
- *
- * Purpose:
- * Looks up the actual OLE descriptive name name in the registration
- * database for the given class name.
- *
- * Parameters:
- * pszClass LPSTR to the class name.
- * psz LPSTR in which to store the descriptive name.
- * cb UINT maximum length of psz.
- *
- * Return Value:
- * UINT Number of characters copied to pszClass. 0 on failure.
- */
- UINT WINAPI UDescriptionFromClass(LPSTR pszClass, LPSTR psz, UINT cb)
- {
- DWORD dw;
- HKEY hKey;
- LONG lRet;
- if (NULL==pszClass || NULL==psz)
- return 0;
- //Open up the root key.
- lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
- if ((LONG)ERROR_SUCCESS!=lRet)
- return 0;
- //Get the descriptive name using the class name.
- dw=(DWORD)cb;
- lRet=RegQueryValue(hKey, pszClass, psz, &dw);
- RegCloseKey(hKey);
- psz+=lstrlen(psz)+1;
- *psz=0;
- if ((LONG)ERROR_SUCCESS!=lRet)
- return 0;
- return (UINT)dw;
- }
- // returns width of line of text. this is a support routine for ChopText
- static LONG GetTextWSize(HDC hDC, LPSTR lpsz)
- {
- SIZE size;
- if (GetTextExtentPoint(hDC, lpsz, lstrlen(lpsz), (LPSIZE)&size))
- return size.cx;
- else {
- return 0;
- }
- }
- /*
- * ChopText
- *
- * Purpose:
- * Parse a string (pathname) and convert it to be within a specified
- * length by chopping the least significant part
- *
- * Parameters:
- * hWnd window handle in which the string resides
- * nWidth max width of string in pixels
- * use width of hWnd if zero
- * lpch pointer to beginning of the string
- *
- * Return Value:
- * pointer to the modified string
- */
- LPSTR WINAPI ChopText(HWND hWnd, int nWidth, LPSTR lpch)
- {
- #define PREFIX_SIZE 7 + 1
- #define PREFIX_FORMAT "%c%c%c...\"
- char szPrefix[PREFIX_SIZE];
- BOOL fDone = FALSE;
- int i;
- RECT rc;
- HDC hdc;
- HFONT hfont;
- HFONT hfontOld = NULL;
- if (!hWnd || !lpch)
- return NULL;
- /* Get length of static field. */
- if (!nWidth) {
- GetClientRect(hWnd, (LPRECT)&rc);
- nWidth = rc.right - rc.left;
- }
- /* Set up DC appropriately for the static control */
- hdc = GetDC(hWnd);
- hfont = (HFONT)SendMessage(hWnd, WM_GETFONT, 0, 0L);
- if (NULL != hfont) // WM_GETFONT returns NULL if window uses system font
- hfontOld = SelectObject(hdc, hfont);
- /* check horizontal extent of string */
- if (GetTextWSize(hdc, lpch) > nWidth) {
- /* string is too long to fit in static control; chop it */
- /* set up new prefix & determine remaining space in control */
- wsprintf(/*(LPSTR)*/ szPrefix, PREFIX_FORMAT, lpch[0], lpch[1], lpch[2]);
- nWidth -= (int)GetTextWSize(hdc, /*(LPSTR)*/ szPrefix);
- /*
- ** advance a directory at a time until the remainder of the
- ** string fits into the static control after the "x:..." prefix
- */
- while (!fDone) {
- #ifdef DBCS
- while (*lpch && (*lpch != '\'))
- lpch = AnsiNext(lpch);
- if (*lpch)
- lpch = AnsiNext(lpch);
- #else
- while (*lpch && (*lpch++ != '\'));
- #endif
- if (!*lpch || GetTextWSize(hdc, lpch) <= nWidth) {
- if (!*lpch)
- /*
- ** Nothing could fit after the prefix; remove the
- ** final "" from the prefix
- */
- szPrefix[lstrlen(/*(LPSTR)*/ szPrefix) - 1] = 0;
- /* rest or string fits -- stick prefix on front */
- for (i = lstrlen(/*(LPSTR)*/ szPrefix) - 1; i >= 0; --i)
- *--lpch = szPrefix[i];
- fDone = TRUE;
- }
- }
- }
- if (NULL != hfont)
- SelectObject(hdc, hfontOld);
- ReleaseDC(hWnd, hdc);
- return(lpch);
- #undef PREFIX_SIZE
- #undef PREFIX_FORMAT
- }
- /*
- * OpenFileError
- *
- * Purpose:
- * display message for error returned from OpenFile
- *
- * Parameters:
- * hDlg HWND of the dialog.
- * nErrCode UINT error code returned in OFSTRUCT passed to OpenFile
- * lpszFile LPSTR file name passed to OpenFile
- *
- * Return Value:
- * None
- */
- void WINAPI OpenFileError(HWND hDlg, UINT nErrCode, LPSTR lpszFile)
- {
- switch (nErrCode) {
- case 0x0005: // Access denied
- ErrorWithFile(hDlg, ghInst, (UINT)IDS_CIFILEACCESS, lpszFile, MB_OK);
- break;
- case 0x0020: // Sharing violation
- ErrorWithFile(hDlg, ghInst, (UINT)IDS_CIFILESHARE, lpszFile, MB_OK);
- break;
- case 0x0002: // File not found
- case 0x0003: // Path not found
- ErrorWithFile(hDlg, ghInst, (UINT)IDS_CIINVALIDFILE, lpszFile, MB_OK);
- break;
- default:
- ErrorWithFile(hDlg, ghInst, (UINT)IDS_CIFILEOPENFAIL, lpszFile, MB_OK);
- break;
- }
- }
- #define chSpace ' '
- #define chPeriod '.'
- #define PARSE_EMPTYSTRING -1
- #define PARSE_INVALIDDRIVE -2
- #define PARSE_INVALIDPERIOD -3
- #define PARSE_INVALIDDIRCHAR -4
- #define PARSE_INVALIDCHAR -5
- #define PARSE_WILDCARDINDIR -6
- #define PARSE_INVALIDNETPATH -7
- #define PARSE_INVALIDSPACE -8
- #define PARSE_EXTENTIONTOOLONG -9
- #define PARSE_DIRECTORYNAME -10
- #define PARSE_FILETOOLONG -11
- /*---------------------------------------------------------------------------
- * ParseFile
- * Purpose: Determine if the filename is a legal DOS name
- * Input: Long pointer to a SINGLE file name
- * Circumstance checked:
- * 1) Valid as directory name, but not as file name
- * 2) Empty String
- * 3) Illegal Drive label
- * 4) Period in invalid location (in extention, 1st in file name)
- * 5) Missing directory character
- * 6) Illegal character
- * 7) Wildcard in directory name
- * 8) Double slash beyond 1st 2 characters
- * 9) Space character in the middle of the name (trailing spaces OK)
- * 10) Filename greater than 8 characters
- * 11) Extention greater than 3 characters
- * Notes:
- * Filename length is NOT checked.
- * Valid filenames will have leading spaces, trailing spaces and
- * terminating period stripped in place.
- *
- * Returns: If valid, LOWORD is byte offset to filename
- * HIWORD is byte offset to extention
- * if string ends with period, 0
- * if no extention is given, string length
- * If invalid, LOWORD is error code suggesting problem (< 0)
- * HIWORD is approximate offset where problem found
- * Note that this may be beyond the offending character
- *--------------------------------------------------------------------------*/
- static long ParseFile(LPSTR lpstrFileName)
- {
- short nFile, nExt, nFileOffset, nExtOffset;
- BOOL bExt;
- BOOL bWildcard;
- short nNetwork = 0;
- BOOL bUNCPath = FALSE;
- LPSTR lpstr = lpstrFileName;
- /* Strip off initial white space. Note that TAB is not checked */
- /* because it cannot be received out of a standard edit control */
- /* 30 January 1991 clarkc */
- while (*lpstr == chSpace)
- lpstr++;
- if (!*lpstr)
- {
- nFileOffset = PARSE_EMPTYSTRING;
- goto FAILURE;
- }
- if (lpstr != lpstrFileName)
- {
- lstrcpy(lpstrFileName, lpstr);
- lpstr = lpstrFileName;
- }
- if (*AnsiNext(lpstr) == ':')
- {
- char cDrive = (*lpstr | (BYTE) 0x20); /* make lowercase */
- /* This does not test if the drive exists, only if it's legal */
- if ((cDrive < 'a') || (cDrive > 'z'))
- {
- nFileOffset = PARSE_INVALIDDRIVE;
- goto FAILURE;
- }
- lpstr = AnsiNext(AnsiNext(lpstr));
- }
- if ((*lpstr == '\') || (*lpstr == '/'))
- {
- if (*++lpstr == chPeriod) /* cannot have c:. */
- {
- if ((*++lpstr != '\') && (*lpstr != '/')) /* unless it's stupid */
- {
- if (!*lpstr) /* it's the root directory */
- goto MustBeDir;
- nFileOffset = PARSE_INVALIDPERIOD;
- goto FAILURE;
- }
- else
- ++lpstr; /* it's saying top directory (again), thus allowed */
- }
- else if ((*lpstr == '\') && (*(lpstr-1) == '\'))
- {
- /* It seems that for a full network path, whether a drive is declared or
- * not is insignificant, though if a drive is given, it must be valid
- * (hence the code above should remain there).
- * 13 February 1991 clarkc
- */
- ++lpstr; /* ...since it's the first slash, 2 are allowed */
- nNetwork = -1; /* Must receive server and share to be real */
- bUNCPath = TRUE; /* No wildcards allowed if UNC name */
- }
- else if (*lpstr == '/')
- {
- nFileOffset = PARSE_INVALIDDIRCHAR;
- goto FAILURE;
- }
- }
- else if (*lpstr == chPeriod)
- {
- if (*++lpstr == chPeriod) /* Is this up one directory? */
- ++lpstr;
- if (!*lpstr)
- goto MustBeDir;
- if ((*lpstr != '\') && (*lpstr != '/'))
- {
- nFileOffset = PARSE_INVALIDPERIOD;
- goto FAILURE;
- }
- else
- ++lpstr; /* it's saying directory, thus allowed */
- }
- if (!*lpstr)
- {
- goto MustBeDir;
- }
- /* Should point to first char in 8.3 filename by now */
- nFileOffset = nExtOffset = nFile = nExt = 0;
- bWildcard = bExt = FALSE;
- while (*lpstr)
- {
- /*
- * The next comparison MUST be unsigned to allow for extended characters!
- * 21 Feb 1991 clarkc
- */
- if (*lpstr < chSpace)
- {
- nFileOffset = PARSE_INVALIDCHAR;
- goto FAILURE;
- }
- switch (*lpstr)
- {
- case '"': /* All invalid */
- case '+':
- case ',':
- case ':':
- case ';':
- case '<':
- case '=':
- case '>':
- case '[':
- case ']':
- case '|':
- {
- nFileOffset = PARSE_INVALIDCHAR;
- goto FAILURE;
- }
- case '\': /* Subdirectory indicators */
- case '/':
- nNetwork++;
- if (bWildcard)
- {
- nFileOffset = PARSE_WILDCARDINDIR;
- goto FAILURE;
- }
- else if (nFile == 0) /* can't have 2 in a row */
- {
- nFileOffset = PARSE_INVALIDDIRCHAR;
- goto FAILURE;
- }
- else
- { /* reset flags */
- ++lpstr;
- if (!nNetwork && !*lpstr)
- {
- nFileOffset = PARSE_INVALIDNETPATH;
- goto FAILURE;
- }
- nFile = nExt = 0;
- bExt = FALSE;
- }
- break;
- case chSpace:
- {
- LPSTR lpSpace = lpstr;
- *lpSpace = ' ';
- while (*++lpSpace)
- {
- if (*lpSpace != chSpace)
- {
- *lpstr = chSpace; /* Reset string, abandon ship */
- nFileOffset = PARSE_INVALIDSPACE;
- goto FAILURE;
- }
- }
- }
- break;
- case chPeriod:
- if (nFile == 0)
- {
- if (*++lpstr == chPeriod)
- ++lpstr;
- if (!*lpstr)
- goto MustBeDir;
- if ((*lpstr != '\') && (*lpstr != '/'))
- {
- nFileOffset = PARSE_INVALIDPERIOD;
- goto FAILURE;
- }
- ++lpstr; /* Flags are already set */
- }
- else if (bExt)
- {
- nFileOffset = PARSE_INVALIDPERIOD; /* can't have one in ext */
- goto FAILURE;
- }
- else
- {
- nExtOffset = 0;
- ++lpstr;
- bExt = TRUE;
- }
- break;
- case '*':
- case '?':
- if (bUNCPath)
- {
- nFileOffset = PARSE_INVALIDNETPATH;
- goto FAILURE;
- }
- bWildcard = TRUE;
- /* Fall through to normal character processing */
- default:
- if (bExt)
- {
- if (++nExt == 1)
- nExtOffset = lpstr - lpstrFileName;
- else if (nExt > 3)
- {
- nFileOffset = PARSE_EXTENTIONTOOLONG;
- goto FAILURE;
- }
- if ((nNetwork == -1) && (nFile + nExt > 11))
- {
- nFileOffset = PARSE_INVALIDNETPATH;
- goto FAILURE;
- }
- }
- else if (++nFile == 1)
- nFileOffset = lpstr - lpstrFileName;
- else if (nFile > 8)
- {
- /* If it's a server name, it can have 11 characters */
- if (nNetwork != -1)
- {
- nFileOffset = PARSE_FILETOOLONG;
- goto FAILURE;
- }
- else if (nFile > 11)
- {
- nFileOffset = PARSE_INVALIDNETPATH;
- goto FAILURE;
- }
- }
- lpstr = AnsiNext(lpstr);
- break;
- }
- }
- /* Did we start with a double backslash but not have any more slashes? */
- if (nNetwork == -1)
- {
- nFileOffset = PARSE_INVALIDNETPATH;
- goto FAILURE;
- }
- if (!nFile)
- {
- MustBeDir:
- nFileOffset = PARSE_DIRECTORYNAME;
- goto FAILURE;
- }
- if ((*(lpstr - 1) == chPeriod) && /* if true, no extention wanted */
- (*AnsiNext(lpstr-2) == chPeriod))
- *(lpstr - 1) = ' '; /* Remove terminating period */
- else if (!nExt)
- FAILURE:
- nExtOffset = lpstr - lpstrFileName;
- return(MAKELONG(nFileOffset, nExtOffset));
- }
- /*
- * DoesFileExist
- *
- * Purpose:
- * Determines if a file path exists
- *
- * Parameters:
- * lpszFile LPSTR - file name
- * lpOpenBuf OFSTRUCT FAR* - points to the OFSTRUCT structure that
- * will receive information about the file when the
- * file is first opened. this field is filled by the
- * Windows OpenFile API.
- *
- * Return Value:
- * HFILE HFILE_ERROR - file does NOT exist
- * file handle (as returned from OpenFile) - file exists
- */
- HFILE WINAPI DoesFileExist(LPSTR lpszFile, OFSTRUCT FAR* lpOpenBuf)
- {
- long nRet;
- int i;
- static char *arrIllegalNames[] = {
- "LPT1",
- "LPT2",
- "LPT3",
- "COM1",
- "COM2",
- "COM3",
- "COM4",
- "CON",
- "AUX",
- "PRN"
- };
- // Check if file name is syntactically correct.
- // (OpenFile sometimes crashes if path is not syntactically correct)
- nRet = ParseFile(lpszFile);
- if (LOWORD(nRet) < 0)
- goto error;
- // Check is the name is an illegal name (eg. the name of a device)
- for (i=0; i < (sizeof(arrIllegalNames)/sizeof(arrIllegalNames[0])); i++) {
- if (lstrcmpi(lpszFile, arrIllegalNames[i])==0)
- goto error; // illegal name FOUND
- }
- return OpenFile(lpszFile, lpOpenBuf, OF_EXIST);
- error:
- _fmemset(lpOpenBuf, 0, sizeof(OFSTRUCT));
- lpOpenBuf->nErrCode = 0x0002; // File not found
- return HFILE_ERROR;
- }