|
|
/*
* comc.c - Shared routines. */
/* Headers
**********/
#include "project.h"
#pragma hdrstop
#include "assoc.h"
#pragma warning(disable:4001) /* "single line comment" warning */
#include "filetype.h"
#pragma warning(default:4001) /* "single line comment" warning */
/* Global Constants
*******************/
#pragma data_seg(DATA_SEG_READ_ONLY)
PUBLIC_DATA const char g_cszWhiteSpace[] = " \t";
PUBLIC_DATA const char g_cszSlashes[] = "/\\";
PUBLIC_DATA const char g_cszPathSeparators[] = ":/\\";
PUBLIC_DATA const char g_cszEditFlags[] = "EditFlags";
#pragma data_seg()
/* Module Constants
*******************/
#pragma data_seg(DATA_SEG_READ_ONLY)
PRIVATE_DATA CCHAR s_cszMIMETypeSubKeyFmt[] = "MIME\\Database\\Content Type\\%s";
PRIVATE_DATA CCHAR s_cszDefaultVerbSubKeyFmt[] = "%s\\Shell"; PRIVATE_DATA CCHAR s_cszShellOpenCmdSubKey[] = "Shell\\Open\\Command";
PRIVATE_DATA CCHAR s_cszContentType[] = "Content Type"; PRIVATE_DATA CCHAR s_cszExtension[] = "Extension";
PRIVATE_DATA const char s_cszAppCmdLineFmt[] = " %s"; PRIVATE_DATA const char s_cszQuotesAppCmdLineFmt[] = " \"%s\"";
#pragma data_seg()
/***************************** Private Functions *****************************/
/*
** GetMIMETypeStringValue() ** ** Retrieves the string for a registered MIME type's value. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE BOOL GetMIMETypeStringValue(PCSTR pcszMIMEType, PCSTR pcszValue, PSTR pszBuf, UINT ucBufLen) { BOOL bResult; DWORD dwValueType; DWORD dwcbLen = ucBufLen;
/* GetMIMEValue() will verify parameters. */
bResult = (GetMIMEValue(pcszMIMEType, pcszValue, &dwValueType, (PBYTE)pszBuf, &dwcbLen) && dwValueType == REG_SZ);
if (! bResult) { if (ucBufLen > 0) *pszBuf = '\0'; }
ASSERT(! ucBufLen || IS_VALID_STRING_PTR(pszBuf, STR));
return(bResult); }
/****************************** Public Functions *****************************/
PUBLIC_CODE BOOL DataCopy(PCBYTE pcbyteSrc, ULONG ulcbLen, PBYTE *ppbyteDest) { BOOL bResult;
ASSERT(IS_VALID_READ_BUFFER_PTR(pcbyteSrc, CBYTE, ulcbLen)); ASSERT(IS_VALID_WRITE_PTR(ppbyteDest, PBYTE));
bResult = AllocateMemory(ulcbLen, ppbyteDest);
if (bResult) CopyMemory(*ppbyteDest, pcbyteSrc, ulcbLen); else *ppbyteDest = NULL;
ASSERT((bResult && IS_VALID_READ_BUFFER_PTR(*ppbyteDest, BYTE, ulcbLen)) || (! bResult && EVAL(! *ppbyteDest)));
return(bResult); }
PUBLIC_CODE BOOL StringCopy(PCSTR pcszSrc, PSTR *ppszCopy) { BOOL bResult;
ASSERT(IS_VALID_STRING_PTR(pcszSrc, CSTR)); ASSERT(IS_VALID_WRITE_PTR(ppszCopy, PSTR));
/* (+ 1) for null terminator. */
bResult = DataCopy((PCBYTE)pcszSrc, lstrlen(pcszSrc) + 1, (PBYTE *)ppszCopy);
ASSERT(! bResult || IS_VALID_STRING_PTR(*ppszCopy, STR));
return(bResult); }
/*
** GetMIMETypeSubKey() ** ** Generates the HKEY_CLASSES_ROOT subkey for a MIME type. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE BOOL GetMIMETypeSubKey(PCSTR pcszMIMEType, PSTR pszSubKeyBuf, UINT ucSubKeyBufLen) { BOOL bResult;
bResult = ((UINT)lstrlen(s_cszMIMETypeSubKeyFmt) + (UINT)lstrlen(pcszMIMEType) < ucSubKeyBufLen);
if (bResult) EVAL((UINT)wsprintf(pszSubKeyBuf, s_cszMIMETypeSubKeyFmt, pcszMIMEType) < ucSubKeyBufLen); else { if (ucSubKeyBufLen > 0) *pszSubKeyBuf = '\0';
WARNING_OUT(("GetMIMETypeSubKey(): Given sub key buffer of length %u is too short to hold sub key for MIME type %s.", ucSubKeyBufLen, pcszMIMEType)); }
ASSERT(! ucSubKeyBufLen || (IS_VALID_STRING_PTR(pszSubKeyBuf, STR) && (UINT)lstrlen(pszSubKeyBuf) < ucSubKeyBufLen)); ASSERT(bResult || ! ucSubKeyBufLen || ! *pszSubKeyBuf);
return(bResult); }
/*
** GetMIMEValue() ** ** Retrieves the data for a value of a MIME type. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE BOOL GetMIMEValue(PCSTR pcszMIMEType, PCSTR pcszValue, PDWORD pdwValueType, PBYTE pbyteValueBuf, PDWORD pdwcbValueBufLen) { BOOL bResult; char szMIMETypeSubKey[MAX_PATH_LEN];
ASSERT(IS_VALID_STRING_PTR(pcszMIMEType, CSTR)); ASSERT(! pcszValue || IS_VALID_STRING_PTR(pcszValue, CSTR)); ASSERT(IS_VALID_WRITE_PTR(pdwValueType, DWORD)); ASSERT(IS_VALID_WRITE_BUFFER_PTR(pbyteValueBuf, BYTE, *pdwcbValueBufLen));
bResult = (GetMIMETypeSubKey(pcszMIMEType, szMIMETypeSubKey, sizeof(szMIMETypeSubKey)) && GetRegKeyValue(HKEY_CLASSES_ROOT, szMIMETypeSubKey, pcszValue, pdwValueType, pbyteValueBuf, pdwcbValueBufLen) == ERROR_SUCCESS);
return(bResult); }
/*
** GetFileTypeValue() ** ** Retrieves the data for a value of the file class associated with an ** extension. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE BOOL GetFileTypeValue(PCSTR pcszExtension, PCSTR pcszSubKey, PCSTR pcszValue, PDWORD pdwValueType, PBYTE pbyteValueBuf, PDWORD pdwcbValueBufLen) { BOOL bResult = FALSE;
ASSERT(IsValidExtension(pcszExtension)); ASSERT(! pcszSubKey || IS_VALID_STRING_PTR(pcszSubKey, CSTR)); ASSERT(! pcszValue || IS_VALID_STRING_PTR(pcszValue, CSTR)); ASSERT(IS_VALID_WRITE_PTR(pdwValueType, DWORD)); ASSERT(IS_VALID_WRITE_BUFFER_PTR(pbyteValueBuf, BYTE, *pdwcbValueBufLen));
if (EVAL(*pcszExtension)) { char szSubKey[MAX_PATH_LEN]; DWORD dwcbLen = sizeof(szSubKey);
/* Get extension's file type. */
if (GetDefaultRegKeyValue(HKEY_CLASSES_ROOT, pcszExtension, szSubKey, &dwcbLen) == ERROR_SUCCESS && *szSubKey) { /* Any sub key to append? */
if (pcszSubKey) { /* Yes. */
/* (+ 1) for possible key separator. */
bResult = EVAL(lstrlen(szSubKey) + 1 + lstrlen(pcszSubKey) < sizeof(szSubKey));
if (bResult) { CatPath(szSubKey, pcszSubKey); ASSERT(lstrlen(szSubKey) < sizeof(szSubKey)); } } else /* No. */ bResult = TRUE;
if (bResult) /* Get file type's value string. */ bResult = (GetRegKeyValue(HKEY_CLASSES_ROOT, szSubKey, pcszValue, pdwValueType, pbyteValueBuf, pdwcbValueBufLen) == ERROR_SUCCESS); } else TRACE_OUT(("GetFileTypeValue(): No file type registered for extension %s.", pcszExtension)); } else WARNING_OUT(("GetFileTypeValue(): No extension given."));
return(bResult); }
/*
** GetMIMEFileTypeValue() ** ** Retrieves the data for a value of the file class associated with a MIME ** type. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE BOOL GetMIMEFileTypeValue(PCSTR pcszMIMEType, PCSTR pcszSubKey, PCSTR pcszValue, PDWORD pdwValueType, PBYTE pbyteValueBuf, PDWORD pdwcbValueBufLen) { BOOL bResult; char szExtension[MAX_PATH_LEN];
ASSERT(IS_VALID_STRING_PTR(pcszMIMEType, CSTR)); ASSERT(! pcszSubKey || IS_VALID_STRING_PTR(pcszSubKey, CSTR)); ASSERT(! pcszValue || IS_VALID_STRING_PTR(pcszValue, CSTR)); ASSERT(IS_VALID_WRITE_PTR(pdwValueType, DWORD)); ASSERT(IS_VALID_WRITE_BUFFER_PTR(pbyteValueBuf, BYTE, *pdwcbValueBufLen));
/* Get file name extension associated with MIME type. */
if (MIME_GetExtension(pcszMIMEType, szExtension, sizeof(szExtension))) bResult = GetFileTypeValue(szExtension, pcszSubKey, pcszValue, pdwValueType, pbyteValueBuf, pdwcbValueBufLen); else { bResult = FALSE;
TRACE_OUT(("GetMIMEFileTypeValue(): No extension registered for MIME type %s.", pcszMIMEType)); }
return(bResult); }
/*
** MIME_IsExternalHandlerRegistered() ** ** Determines whether or not an external handler is registered for a MIME type. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE BOOL MIME_IsExternalHandlerRegistered(PCSTR pcszMIMEType) { BOOL bResult; DWORD dwValueType; char szOpenCmd[MAX_PATH_LEN]; DWORD dwcbOpenCmdLen = sizeof(szOpenCmd);
/* GetMIMEFileTypeValue() will verify parameters. */
/* Look up the open command of the MIME type's associated file type. */
bResult = (GetMIMEFileTypeValue(pcszMIMEType, s_cszShellOpenCmdSubKey, NULL, &dwValueType, (PBYTE)szOpenCmd, &dwcbOpenCmdLen) && dwValueType == REG_SZ);
TRACE_OUT(("MIME_IsExternalHandlerRegistered(): %s external handler is registered for MIME type %s.", bResult ? "An" : "No", pcszMIMEType));
return(bResult); }
/*
** MIME_GetExtension() ** ** Determines the file name extension to be used when writing a file of a MIME ** type to the file system. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE BOOL MIME_GetExtension(PCSTR pcszMIMEType, PSTR pszExtensionBuf, UINT ucExtensionBufLen) { BOOL bResult = FALSE;
ASSERT(IS_VALID_STRING_PTR(pcszMIMEType, CSTR)); ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszExtensionBuf, STR, ucExtensionBufLen));
if (EVAL(ucExtensionBufLen > 2)) { /* Leave room for possible leading period. */
if (GetMIMETypeStringValue(pcszMIMEType, s_cszExtension, pszExtensionBuf + 1, ucExtensionBufLen - 1)) { if (pszExtensionBuf[1]) { /* Prepend period if necessary. */
if (pszExtensionBuf[1] == PERIOD) /* (+ 1) for null terminator. */ MoveMemory(pszExtensionBuf, pszExtensionBuf + 1, lstrlen(pszExtensionBuf + 1) + 1); else pszExtensionBuf[0] = PERIOD;
bResult = TRUE; } } }
if (! bResult) { if (ucExtensionBufLen > 0) *pszExtensionBuf = '\0'; }
if (bResult) TRACE_OUT(("MIME_GetExtension(): Extension %s registered as default extension for MIME type %s.", pszExtensionBuf, pcszMIMEType)); else TRACE_OUT(("MIME_GetExtension(): No default extension registered for MIME type %s.", pcszMIMEType));
ASSERT((bResult && IsValidExtension(pszExtensionBuf)) || (! bResult && (! ucExtensionBufLen || ! *pszExtensionBuf))); ASSERT(! ucExtensionBufLen || (UINT)lstrlen(pszExtensionBuf) < ucExtensionBufLen);
return(bResult); }
/*
** MIME_GetMIMETypeFromExtension() ** ** Determines the MIME type associated with a file extension. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE BOOL MIME_GetMIMETypeFromExtension(PCSTR pcszPath, PSTR pszMIMETypeBuf, UINT ucMIMETypeBufLen) { BOOL bResult; PCSTR pcszExtension;
ASSERT(IS_VALID_STRING_PTR(pcszPath, CSTR)); ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszMIMETypeBuf, STR, ucMIMETypeBufLen));
pcszExtension = ExtractExtension(pcszPath);
if (*pcszExtension) { DWORD dwcLen = ucMIMETypeBufLen;
bResult = (GetRegKeyStringValue(HKEY_CLASSES_ROOT, pcszExtension, s_cszContentType, pszMIMETypeBuf, &dwcLen) == ERROR_SUCCESS);
if (bResult) TRACE_OUT(("MIME_GetMIMETypeFromExtension(): MIME type for extension %s is %s.",
pcszExtension, pszMIMETypeBuf)); else TRACE_OUT(("MIME_GetMIMETypeFromExtension(): No MIME type registered for extension %s.", pcszExtension)); } else { bResult = FALSE;
TRACE_OUT(("MIME_GetMIMETypeFromExtension(): No extension in path %s.", pcszPath)); }
if (! bResult) { if (ucMIMETypeBufLen > 0) *pszMIMETypeBuf = '\0'; }
ASSERT(! ucMIMETypeBufLen || (IS_VALID_STRING_PTR(pszMIMETypeBuf, STR) && (UINT)lstrlen(pszMIMETypeBuf) < ucMIMETypeBufLen)); ASSERT(bResult || ! ucMIMETypeBufLen || ! *pszMIMETypeBuf);
return(bResult); }
/*
** CatPath() ** ** Appends a filename to a path string. ** ** Arguments: pszPath - path string that file name is to be appended to ** pcszSubPath - path to append ** ** Returns: void ** ** Side Effects: none ** ** N.b., truncates path to MAX_PATH_LEN characters in length. ** ** Examples: ** ** input path input file name output path ** ---------- --------------- ----------- ** c:\ foo c:\foo ** c: foo c:foo ** c:\foo\bar\ goo c:\foo\bar\goo ** c:\foo\bar\ \goo c:\foo\bar\goo ** c:\foo\bar\ goo\shoe c:\foo\bar\goo\shoe ** c:\foo\bar\ \goo\shoe\ c:\foo\bar\goo\shoe\ ** foo\bar\ goo foo\bar\goo ** <empty string> <empty string> <empty string> ** <empty string> foo foo ** foo <empty string> foo ** fred bird fred\bird */ PUBLIC_CODE void CatPath(PSTR pszPath, PCSTR pcszSubPath) { PSTR pcsz; PSTR pcszLast;
ASSERT(IS_VALID_STRING_PTR(pszPath, STR)); ASSERT(IS_VALID_STRING_PTR(pcszSubPath, CSTR)); /* (+ 1) for possible separator. */ /* (+ 1) for null terminator. */ ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszPath, STR, lstrlen(pszPath) + 1 + lstrlen(pcszSubPath) + 1));
/* Find last character in path string. */
for (pcsz = pcszLast = pszPath; *pcsz; pcsz = CharNext(pcsz)) pcszLast = pcsz;
if (IS_SLASH(*pcszLast) && IS_SLASH(*pcszSubPath)) pcszSubPath++; else if (! IS_SLASH(*pcszLast) && ! IS_SLASH(*pcszSubPath)) { if (*pcszLast && *pcszLast != COLON && *pcszSubPath) *pcsz++ = '\\'; }
lstrcpy(pcsz, pcszSubPath);
ASSERT(IS_VALID_STRING_PTR(pszPath, STR));
return; }
/*
** MyLStrCpyN() ** ** Like lstrcpy(), but the copy is limited to ucb bytes. The destination ** string is always null-terminated. ** ** Arguments: pszDest - pointer to destination buffer ** pcszSrc - pointer to source string ** ncb - maximum number of bytes to copy, including null ** terminator ** ** Returns: void ** ** Side Effects: none ** ** N.b., this function behaves quite differently than strncpy()! It does not ** pad out the destination buffer with null characters, and it always null ** terminates the destination string. */ PUBLIC_CODE void MyLStrCpyN(PSTR pszDest, PCSTR pcszSrc, int ncb) { ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszDest, STR, ncb)); ASSERT(IS_VALID_STRING_PTR(pcszSrc, CSTR)); ASSERT(ncb > 0);
while (ncb > 1) { ncb--;
*pszDest = *pcszSrc;
if (*pcszSrc) { pszDest++; pcszSrc++; } else break; }
if (ncb == 1) *pszDest = '\0';
ASSERT(IS_VALID_STRING_PTR(pszDest, STR)); ASSERT(lstrlen(pszDest) < ncb); ASSERT(lstrlen(pszDest) <= lstrlen(pcszSrc));
return; }
PUBLIC_CODE COMPARISONRESULT MapIntToComparisonResult(int nResult) { COMPARISONRESULT cr;
/* Any integer is valid input. */
if (nResult < 0) cr = CR_FIRST_SMALLER; else if (nResult > 0) cr = CR_FIRST_LARGER; else cr = CR_EQUAL;
return(cr); }
/*
** TrimWhiteSpace() ** ** Trims leading and trailing white space from a string in place. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE void TrimWhiteSpace(PSTR pszTrimMe) { ASSERT(IS_VALID_STRING_PTR(pszTrimMe, STR));
TrimString(pszTrimMe, g_cszWhiteSpace);
/* TrimString() validates pszTrimMe on output. */
return; }
/*
** TrimSlashes() ** ** Trims leading and trailing slashes from a string in place. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE void TrimSlashes(PSTR pszTrimMe) { ASSERT(IS_VALID_STRING_PTR(pszTrimMe, STR));
TrimString(pszTrimMe, g_cszSlashes);
/* TrimString() validates pszTrimMe on output. */
return; }
PUBLIC_CODE void TrimString(PSTR pszTrimMe, PCSTR pszTrimChars) { PSTR psz; PSTR pszStartMeat;
ASSERT(IS_VALID_STRING_PTR(pszTrimMe, STR)); ASSERT(IS_VALID_STRING_PTR(pszTrimChars, CSTR));
if ( !pszTrimMe ) return;
/* Trim leading characters. */
psz = pszTrimMe;
while (*psz && strchr(pszTrimChars, *psz)) psz = CharNext(psz);
pszStartMeat = psz;
/* Trim trailing characters. */
if (*psz) { psz += lstrlen(psz);
psz = CharPrev(pszStartMeat, psz);
if (psz > pszStartMeat) { while (strchr(pszTrimChars, *psz)) psz = CharPrev(pszStartMeat, psz);
psz = CharNext(psz);
ASSERT(psz > pszStartMeat);
*psz = '\0'; } }
/* Relocate stripped string. */
if (pszStartMeat > pszTrimMe) /* (+ 1) for null terminator. */ MoveMemory(pszTrimMe, pszStartMeat, lstrlen(pszStartMeat) + 1); else ASSERT(pszStartMeat == pszTrimMe);
ASSERT(IS_VALID_STRING_PTR(pszTrimMe, STR));
return; }
/*
** ExtractFileName() ** ** Extracts the file name from a path name. ** ** Arguments: pcszPathName - path string from which to extract file name ** ** Returns: Pointer to file name in path string. ** ** Side Effects: none */ PUBLIC_CODE PCSTR ExtractFileName(PCSTR pcszPathName) { PCSTR pcszLastComponent; PCSTR pcsz;
ASSERT(IS_VALID_STRING_PTR(pcszPathName, CSTR));
for (pcszLastComponent = pcsz = pcszPathName; *pcsz; pcsz = CharNext(pcsz)) { if (IS_SLASH(*pcsz) || *pcsz == COLON) pcszLastComponent = CharNext(pcsz); }
ASSERT(IsValidPath(pcszLastComponent));
return(pcszLastComponent); }
/*
** ExtractExtension() ** ** Extracts the extension from a name. ** ** Arguments: pcszName - name whose extension is to be extracted ** ** Returns: If the name contains an extension, a pointer to the period at ** the beginning of the extension is returned. If the name has ** no extension, a pointer to the name's null terminator is ** returned. ** ** Side Effects: none */ PUBLIC_CODE PCSTR ExtractExtension(PCSTR pcszName) { PCSTR pcszLastPeriod;
ASSERT(IS_VALID_STRING_PTR(pcszName, CSTR));
/* Make sure we have an isolated file name. */
pcszName = ExtractFileName(pcszName);
pcszLastPeriod = NULL;
while (*pcszName) { if (*pcszName == PERIOD) pcszLastPeriod = pcszName;
pcszName = CharNext(pcszName); }
if (! pcszLastPeriod) { /* Point at null terminator. */
pcszLastPeriod = pcszName; ASSERT(! *pcszLastPeriod); } else /* Point at period at beginning of extension. */ ASSERT(*pcszLastPeriod == PERIOD);
ASSERT(! *pcszLastPeriod || IsValidExtension(pcszLastPeriod));
return(pcszLastPeriod); }
/*
** SetRegKeyValue() ** ** Sets the data associated with a registry key's value. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE LONG SetRegKeyValue(HKEY hkeyParent, PCSTR pcszSubKey, PCSTR pcszValue, DWORD dwType, PCBYTE pcbyte, DWORD dwcb) { LONG lResult; HKEY hkeySubKey;
ASSERT(IS_VALID_HANDLE(hkeyParent, KEY)); ASSERT(IS_VALID_STRING_PTR(pcszSubKey, CSTR)); ASSERT(IsValidRegistryValueType(dwType)); ASSERT(! pcszValue || IS_VALID_STRING_PTR(pcszValue, CSTR)); ASSERT(IS_VALID_READ_BUFFER_PTR(pcbyte, CBYTE, dwcb));
lResult = RegCreateKeyEx(hkeyParent, pcszSubKey, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkeySubKey, NULL);
if (lResult == ERROR_SUCCESS) { LONG lResultClose;
lResult = RegSetValueEx(hkeySubKey, pcszValue, 0, dwType, pcbyte, dwcb);
lResultClose = RegCloseKey(hkeySubKey);
if (lResult == ERROR_SUCCESS) lResult = lResultClose; }
return(lResult); }
/*
** GetRegKeyValue() ** ** Retrieves the data from a registry key's value. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE LONG GetRegKeyValue(HKEY hkeyParent, PCSTR pcszSubKey, PCSTR pcszValue, PDWORD pdwValueType, PBYTE pbyteBuf, PDWORD pdwcbBufLen) { LONG lResult; HKEY hkeySubKey;
ASSERT(IS_VALID_HANDLE(hkeyParent, KEY)); ASSERT(! pcszSubKey || IS_VALID_STRING_PTR(pcszSubKey, CSTR)); ASSERT(! pcszValue || IS_VALID_STRING_PTR(pcszValue, CSTR)); ASSERT(! pdwValueType || IS_VALID_WRITE_PTR(pdwValueType, DWORD)); ASSERT(! pbyteBuf || IS_VALID_WRITE_BUFFER_PTR(pbyteBuf, BYTE, *pdwcbBufLen));
lResult = RegOpenKeyEx(hkeyParent, pcszSubKey, 0, KEY_QUERY_VALUE, &hkeySubKey);
if (lResult == ERROR_SUCCESS) { LONG lResultClose;
lResult = RegQueryValueEx(hkeySubKey, pcszValue, NULL, pdwValueType, pbyteBuf, pdwcbBufLen);
lResultClose = RegCloseKey(hkeySubKey);
if (lResult == ERROR_SUCCESS) lResult = lResultClose; }
return(lResult); }
/*
** GetRegKeyStringValue() ** ** Retrieves the data from a registry key's string value. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE LONG GetRegKeyStringValue(HKEY hkeyParent, PCSTR pcszSubKey, PCSTR pcszValue, PSTR pszBuf, PDWORD pdwcbBufLen) { LONG lResult; DWORD dwValueType;
/* GetRegKeyValue() will verify the parameters. */
lResult = GetRegKeyValue(hkeyParent, pcszSubKey, pcszValue, &dwValueType, (PBYTE)pszBuf, pdwcbBufLen);
if (lResult == ERROR_SUCCESS && dwValueType != REG_SZ) lResult = ERROR_CANTREAD;
return(lResult); }
/*
** GetDefaultRegKeyValue() ** ** Retrieves the data from a registry key's default string value. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE LONG GetDefaultRegKeyValue(HKEY hkeyParent, PCSTR pcszSubKey, PSTR pszBuf, PDWORD pdwcbBufLen) { /* GetRegKeyStringValue() will verify the parameters. */
return(GetRegKeyStringValue(hkeyParent, pcszSubKey, NULL, pszBuf, pdwcbBufLen)); }
/*
** FullyQualifyPath() ** ** Fully qualifies a path. ** ** Arguments: ** ** Returns: S_OK ** ** E_FILE_NOT_FOUND ** ** Side Effects: none */ PUBLIC_CODE HRESULT FullyQualifyPath(PCSTR pcszPath, PSTR pszFullyQualifiedPath, UINT ucFullyQualifiedPathBufLen) { HRESULT hr = E_FILE_NOT_FOUND; PSTR pszFileName;
ASSERT(IS_VALID_STRING_PTR(pcszPath, CSTR));
/* Any path separators? */
if (! strpbrk(pcszPath, g_cszPathSeparators)) { /* No. Search for file. */
TRACE_OUT(("FullyQualifyPath(): Searching PATH for %s.", pcszPath));
if (SearchPath(NULL, pcszPath, NULL, ucFullyQualifiedPathBufLen, pszFullyQualifiedPath, &pszFileName) > 0) hr = S_OK; else TRACE_OUT(("FullyQualifyPath(): %s not found on PATH.", pcszPath)); }
if (hr != S_OK && GetFullPathName(pcszPath, ucFullyQualifiedPathBufLen, pszFullyQualifiedPath, &pszFileName) > 0) hr = S_OK;
if (hr == S_OK) TRACE_OUT(("FullyQualifyPath(): %s qualified as %s.", pcszPath, pszFullyQualifiedPath)); else { if (ucFullyQualifiedPathBufLen > 0) pszFullyQualifiedPath = '\0';
WARNING_OUT(("FullyQualifyPath(): Failed to qualify %s.", pcszPath)); }
ASSERT((hr == S_OK && EVAL(IsFullPath(pszFullyQualifiedPath))) || (hr == E_FILE_NOT_FOUND && (! ucFullyQualifiedPathBufLen || ! *pszFullyQualifiedPath)));
return(hr); }
/*
** MyExecute() ** ** Calls CreateProcess() politely. ** ** Arguments: ** ** Returns: S_OK ** ** E_FAIL ** E_FILE_NOT_FOUND ** E_OUTOFMEMORY ** ** Side Effects: none */ PUBLIC_CODE HRESULT MyExecute(PCSTR pcszApp, PCSTR pcszArgs, DWORD dwInFlags) { HRESULT hr; char szFullApp[MAX_PATH_LEN];
ASSERT(IS_VALID_STRING_PTR(pcszApp, CSTR)); ASSERT(IS_VALID_STRING_PTR(pcszArgs, CSTR)); ASSERT(FLAGS_ARE_VALID(dwInFlags, ALL_ME_IN_FLAGS));
hr = FullyQualifyPath(pcszApp, szFullApp, sizeof(szFullApp));
if (hr == S_OK) { DWORD dwcbCmdLineLen; PSTR pszCmdLine;
/* (+ 1) for null terminator. */ dwcbCmdLineLen = max(sizeof(s_cszAppCmdLineFmt), sizeof(s_cszQuotesAppCmdLineFmt)) + + lstrlen(pcszArgs) + 1;
if (AllocateMemory(dwcbCmdLineLen * sizeof(*pszCmdLine), &pszCmdLine)) { PCSTR pcszFmt; STARTUPINFO si; PROCESS_INFORMATION pi;
/* Execute URL via one-shot app. */
pcszFmt = (IS_FLAG_SET(dwInFlags, ME_IFL_QUOTE_ARGS) && strpbrk(pcszArgs, g_cszWhiteSpace) != NULL) ? s_cszQuotesAppCmdLineFmt : s_cszAppCmdLineFmt;
EVAL((DWORD)wsprintf(pszCmdLine, pcszFmt, pcszArgs) < dwcbCmdLineLen);
ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si);
/* Specify command line exactly as given to app. */
if (CreateProcess(szFullApp, pszCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { CloseHandle(pi.hProcess); CloseHandle(pi.hThread);
hr = S_OK;
TRACE_OUT(("MyExecute(): CreateProcess() \"%s %s\" succeeded.", szFullApp, pszCmdLine)); } else { hr = E_FAIL;
WARNING_OUT(("MyExecute(): CreateProcess() \"%s %s\" failed.", szFullApp, pszCmdLine)); }
FreeMemory(pszCmdLine); pszCmdLine = NULL; } else hr = E_OUTOFMEMORY; } else WARNING_OUT(("MyExecute(): Unable to find app %s.", pcszApp));
return(hr); }
PUBLIC_CODE BOOL GetClassDefaultVerb(PCSTR pcszClass, PSTR pszDefaultVerbBuf, UINT ucDefaultVerbBufLen) { BOOL bResult; char szDefaultVerbSubKey[MAX_PATH_LEN];
ASSERT(IS_VALID_STRING_PTR(pcszClass, CSTR)); ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszDefaultVerbBuf, STR, ucDefaultVerbBufLen));
ASSERT(lstrlen(pcszClass) > 0);
if (sizeof(s_cszDefaultVerbSubKeyFmt) + lstrlen(pcszClass) < sizeof(szDefaultVerbSubKey)) { DWORD dwValueType; DWORD dwcbBufLen = ucDefaultVerbBufLen;
EVAL(wsprintf(szDefaultVerbSubKey, s_cszDefaultVerbSubKeyFmt, pcszClass) < sizeof(szDefaultVerbSubKey));
bResult = (GetRegKeyValue(HKEY_CLASSES_ROOT, szDefaultVerbSubKey, NULL, &dwValueType, (PBYTE)pszDefaultVerbBuf, &dwcbBufLen) == ERROR_SUCCESS && dwValueType == REG_SZ && *pszDefaultVerbBuf); } else bResult = FALSE;
if (! bResult) { if (ucDefaultVerbBufLen > 0) *pszDefaultVerbBuf = '\0'; }
if (bResult) TRACE_OUT(("GetClassDefaultVerb(): Default verb for %s class is %s.", pcszClass, pszDefaultVerbBuf)); else TRACE_OUT(("GetClassDefaultVerb(): No default verb for %s class.", pcszClass));
ASSERT(! ucDefaultVerbBufLen || (IS_VALID_STRING_PTR(pszDefaultVerbBuf, STR) && EVAL((UINT)lstrlen(pszDefaultVerbBuf) < ucDefaultVerbBufLen))); ASSERT(bResult || ! ucDefaultVerbBufLen || ! *pszDefaultVerbBuf);
return(bResult); }
/*
* APPCOMPAT: The need for this function should be obviated by a ShellExecuteEx() * flag indicating that the default verb, rather than the open verb, should be * executed. This is broken for folders, for compound document files, for * files whose extensions are registered without a file class, for files whose * extensions are not unregistered, etc. */ PUBLIC_CODE BOOL GetPathDefaultVerb(PCSTR pcszPath, PSTR pszDefaultVerbBuf, UINT ucDefaultVerbBufLen) { BOOL bResult = FALSE; PCSTR pcszExtension; char szClass[MAX_PATH_LEN]; DWORD dwcbLen = ucDefaultVerbBufLen;
ASSERT(IsValidPath(pcszPath)); ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszDefaultVerbBuf, STR, ucDefaultVerbBufLen));
pcszExtension = ExtractExtension(pcszPath);
bResult = (*pcszExtension && GetDefaultRegKeyValue(HKEY_CLASSES_ROOT, pcszExtension, szClass, &dwcbLen) == ERROR_SUCCESS && *szClass && GetClassDefaultVerb(szClass, pszDefaultVerbBuf, ucDefaultVerbBufLen));
if (! bResult) { if (ucDefaultVerbBufLen > 0) *pszDefaultVerbBuf = '\0'; }
ASSERT(! ucDefaultVerbBufLen || (IS_VALID_STRING_PTR(pszDefaultVerbBuf, STR) && EVAL((UINT)lstrlen(pszDefaultVerbBuf) < ucDefaultVerbBufLen))); ASSERT(bResult || ! ucDefaultVerbBufLen || ! *pszDefaultVerbBuf);
return(bResult); }
/*
** ClassIsSafeToOpen() ** ** Determines whether or not a file class is known safe to open. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE BOOL ClassIsSafeToOpen(PCSTR pcszClass) { BOOL bSafe; DWORD dwValueType; DWORD dwEditFlags; DWORD dwcbLen = sizeof(dwEditFlags);
ASSERT(IS_VALID_STRING_PTR(pcszClass, CSTR));
bSafe = (GetRegKeyValue(HKEY_CLASSES_ROOT, pcszClass, g_cszEditFlags, &dwValueType, (PBYTE)&dwEditFlags, &dwcbLen) == ERROR_SUCCESS && (dwValueType == REG_BINARY || dwValueType == REG_DWORD) && IS_FLAG_SET(dwEditFlags, FTA_OpenIsSafe));
TRACE_OUT(("ClassIsSafeToOpen(): Class %s %s safe to open.", pcszClass, bSafe ? "is" : "is not"));
return(bSafe); }
/*
** SetClassEditFlags() ** ** Sets or clears EditFlags for a file class. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE BOOL SetClassEditFlags(PCSTR pcszClass, DWORD dwFlags, BOOL bSet) { BOOL bResult = FALSE; DWORD dwValueType; DWORD dwEditFlags; DWORD dwcbLen = sizeof(dwEditFlags);
ASSERT(IS_VALID_STRING_PTR(pcszClass, CSTR));
/* Get current file class flags. */
if (GetRegKeyValue(HKEY_CLASSES_ROOT, pcszClass, g_cszEditFlags, &dwValueType, (PBYTE)&dwEditFlags, &dwcbLen) != ERROR_SUCCESS || (dwValueType != REG_BINARY && dwValueType != REG_DWORD)) dwEditFlags = 0;
/* Set or clear SafeOpen flag for file class. */
if (bSet) SET_FLAG(dwEditFlags, dwFlags); else CLEAR_FLAG(dwEditFlags, dwFlags);
/*
* N.b., we must set this as REG_BINARY because the base Win95 shell32.dll * only accepts REG_BINARY EditFlags. */
bResult = (SetRegKeyValue(HKEY_CLASSES_ROOT, pcszClass, g_cszEditFlags, REG_BINARY, (PCBYTE)&dwEditFlags, sizeof(dwEditFlags)) == ERROR_SUCCESS);
if (bResult) TRACE_OUT(("SetClassEditFlags(): Class %s flags %lu %s.", pcszClass, dwFlags, bSet ? "set" : "cleared")); else WARNING_OUT(("SetClassEditFlags(): Failed to %s class %s flags %lu.", bSet ? "set" : "clear", pcszClass, dwFlags));
return(bResult); }
#ifdef DEBUG
PUBLIC_CODE BOOL IsFullPath(PCSTR pcszPath) { BOOL bResult = FALSE; char rgchFullPath[MAX_PATH_LEN];
if (IS_VALID_STRING_PTR(pcszPath, CSTR) && EVAL(lstrlen(pcszPath) < MAX_PATH_LEN)) { DWORD dwPathLen; PSTR pszFileName;
dwPathLen = GetFullPathName(pcszPath, sizeof(rgchFullPath), rgchFullPath, &pszFileName);
if (EVAL(dwPathLen > 0) && EVAL(dwPathLen < sizeof(rgchFullPath))) bResult = EVAL(! lstrcmpi(pcszPath, rgchFullPath)); }
return(bResult); }
#endif /* DEBUG */
|