//********************************************************************* //* Microsoft Windows ** //* Copyright(c) Microsoft Corp., 1995 ** //********************************************************************* // // HELPERS.CPP // // HISTORY: // // 9/01/95 philco Created. // // #include BOOL GetEXEName(LPSTR szCmdLine); ///////*********** Helper functions *********///////////// /******************************************************************* NAME: Unicode2Ansi SYNOPSIS: Converts a unicode widechar string to ansi (MBCS) NOTES: Caller must free out parameter using delete ********************************************************************/ HRESULT Unicode2Ansi(const wchar_t *src, char ** dest) { if ((src == NULL) || (dest == NULL)) return E_INVALIDARG; // find out required buffer size and allocate it. int len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL); *dest = new char [len*sizeof(char)]; if (!*dest) return E_OUTOFMEMORY; // Now do the actual conversion if ((WideCharToMultiByte(CP_ACP, 0, src, -1, *dest, len*sizeof(char), NULL, NULL)) != 0) return S_OK; else return E_FAIL; } /******************************************************************* NAME: Ansi2Unicode SYNOPSIS: Converts an ansi (MBCS) string to unicode. Notes: Caller must free out parameter using delete ********************************************************************/ HRESULT Ansi2Unicode(const char * src, wchar_t **dest) { if ((src == NULL) || (dest == NULL)) return E_INVALIDARG; // find out required buffer size and allocate it int len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, -1, NULL, 0); *dest = new WCHAR [len*sizeof(WCHAR)]; if (!*dest) return E_OUTOFMEMORY; // Do the actual conversion. if ((MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, -1, *dest, len*sizeof(wchar_t))) != 0) return S_OK; else return E_FAIL; } /******************************************************************* NAME: ConvertANSItoCLSID SYNOPSIS: Converts an ANSI string to a CLSID structure (address of which is passed by caller as an [out] parameter) ********************************************************************/ HRESULT ConvertANSItoCLSID(const char *pszCLSID, CLSID * clsid) { ASSERT(pszCLSID != NULL); ASSERT(clsid != NULL); HRESULT hr = S_OK; LPOLESTR wcstr = NULL; // Since OLE is Unicode only, we need to convert pszClsid to Unicode. hr = Ansi2Unicode(pszCLSID, &wcstr); if (FAILED(hr)) goto cleanup; // Get CLSID from string hr = CLSIDFromString(wcstr, clsid); if (FAILED(hr)) goto cleanup; cleanup: if (wcstr != NULL) delete wcstr; // Delete unicode string. We're done. return hr; } /******************************************************************* NAME: ConvertFriendlyANSItoCLSID SYNOPSIS: Works like ConvertANSItoCLSID but allows prefix of "clsid:" CLSID is passed as [out] parameter. ********************************************************************/ HRESULT ConvertFriendlyANSItoCLSID(char *pszCLSID, CLSID * clsid) { static const char *szClsid = "clsid:"; ASSERT(pszCLSID != NULL); ASSERT(clsid != NULL); HRESULT hr = S_OK; // try OLE form. hr = ConvertANSItoCLSID(pszCLSID,clsid); if (SUCCEEDED(hr)) goto cleanup; // try for prefix "clsid:" if (StrCmpNA(pszCLSID, szClsid, lstrlenA(szClsid)) == 0) { hr = ConvertANSItoCLSID(pszCLSID + lstrlenA(szClsid), clsid); if (SUCCEEDED(hr)) goto cleanup; // construct COM form of clsid: LPSTR szTmp = NULL; szTmp = new char[lstrlenA(pszCLSID) - lstrlenA(szClsid) + 2 + 1]; if (!szTmp) { hr = E_OUTOFMEMORY; goto cleanup; } lstrcpyA(szTmp,"{"); lstrcatA(szTmp,pszCLSID + lstrlenA(szClsid)); lstrcatA(szTmp,"}"); hr = ConvertANSItoCLSID(szTmp,clsid); delete [] szTmp; if (SUCCEEDED(hr)) goto cleanup; } // error code passes through cleanup: return hr; } // --------------------------------------------------------------------------- // %%Function: GetExtnAndBaseFileName // // Parameters: // in szName: a filename or URL // out update pbasefilename to point into this szName // // Returns: // out: extn // --------------------------------------------------------------------------- FILEXTN GetExtnAndBaseFileName( char *szName, char **plpBaseFileName) { char *pCur = szName; char *pExt = NULL; char szExtCopy[4]; FILEXTN extn = FILEXTN_UNKNOWN; const static char *szCAB = "CAB"; const static char *szINF = "INF"; const static char *szDLL = "DLL"; const static char *szOCX = "OCX"; const static char *szEXE = "EXE"; const static char *szOSD = "OSD"; const static char *szCAT = "CAT"; *plpBaseFileName = szName; // find location of last '.' and '/' in name for (;*pCur; *pCur++) { if (*pCur == '.') pExt = pCur+1; if ((*pCur == '/') || (*pCur == '\\')) *plpBaseFileName = pCur+1; } if (!pExt || !*pExt) { // if no '.' or as last char extn = FILEXTN_NONE; goto Exit; } StrNCpy(szExtCopy, pExt, 4); CharUpperBuff(szExtCopy, 3); if (lstrcmp(szExtCopy, szCAB) == 0) { extn = FILEXTN_CAB; goto Exit; } if (lstrcmp(szExtCopy, szOCX) == 0) { extn = FILEXTN_OCX; goto Exit; } if (lstrcmp(szExtCopy, szDLL) == 0) { extn = FILEXTN_DLL; goto Exit; } if (lstrcmp(szExtCopy, szEXE) == 0) { extn = FILEXTN_EXE; goto Exit; } if (lstrcmp(szExtCopy, szINF) == 0) { extn = FILEXTN_INF; goto Exit; } if (lstrcmp(szExtCopy, szOSD) == 0) { extn = FILEXTN_OSD; goto Exit; } if (lstrcmp(szExtCopy, szCAT) == 0) { extn = FILEXTN_CAT; goto Exit; } Exit: return extn; } // --------------------------------------------------------------------------- // %%Function: GetVersionFromString // // converts version in text format (a,b,c,d) into two dwords (a,b), (c,d) // The printed version number is of format a.b.d (but, we don't care) // --------------------------------------------------------------------------- HRESULT GetVersionFromString(const char *szBuf, LPDWORD pdwFileVersionMS, LPDWORD pdwFileVersionLS, char cSeperator) { // cdl.h defines cSeperator as a default parameter: ',' const char *pch = szBuf; char ch; char szMaxString[30]; *pdwFileVersionMS = 0; *pdwFileVersionLS = 0; if (!pch) // default to zero if none provided return S_OK; wsprintf(szMaxString, "-1%c-1%c-1%c-1", cSeperator, cSeperator, cSeperator); if (lstrcmp(pch, szMaxString) == 0) { *pdwFileVersionMS = 0xffffffff; *pdwFileVersionLS = 0xffffffff; return S_OK; } USHORT n = 0; USHORT a = 0; USHORT b = 0; USHORT c = 0; USHORT d = 0; enum HAVE { HAVE_NONE, HAVE_A, HAVE_B, HAVE_C, HAVE_D } have = HAVE_NONE; for (ch = *pch++;;ch = *pch++) { if ((ch == cSeperator) || (ch == '\0')) { switch (have) { case HAVE_NONE: a = n; have = HAVE_A; break; case HAVE_A: b = n; have = HAVE_B; break; case HAVE_B: c = n; have = HAVE_C; break; case HAVE_C: d = n; have = HAVE_D; break; case HAVE_D: return E_INVALIDARG; // invalid arg } if (ch == '\0') { // all done convert a,b,c,d into two dwords of version *pdwFileVersionMS = ((a << 16)|b); *pdwFileVersionLS = ((c << 16)|d); return S_OK; } n = 0; // reset } else if ( (ch < '0') || (ch > '9')) return E_INVALIDARG; // invalid arg else n = n*10 + (ch - '0'); } /* end forever */ // NEVERREACHED } //************************************************************ // CheckFileImplementsCLSID // // checks if a clsid is implemented by the given file // Return S_OK on success. // // pszFileName: Full path to the file whose clsid we // desire. // rClsid: clsid to check // HRESULT CheckFileImplementsCLSID(const char *pszFileName, REFCLSID rClsid) { LPTYPELIB ptlib = NULL; LPTYPEINFO lpTypeInfo = NULL; LPTYPEATTR lpTypeAttr = NULL; WCHAR puszFileName[MAX_PATH]; // unicode string HRESULT hr = S_OK; // // LoadTypeLib() needs the string in unicode. // MultiByteToWideChar(CP_ACP, 0, pszFileName, -1, puszFileName, sizeof(puszFileName) / sizeof(wchar_t)); hr = LoadTypeLib(puszFileName, &ptlib); if (FAILED(hr)) return hr; hr = ptlib->GetTypeInfoOfGuid(rClsid, &lpTypeInfo); if (SUCCEEDED(hr)) { if (S_OK != (hr = lpTypeInfo->GetTypeAttr(&lpTypeAttr))) { goto Exit; } if (TKIND_COCLASS == lpTypeAttr->typekind) { Assert(IsEqualGUID( lpTypeAttr->guid, rClsid)); // success goto Exit; } } Exit: if (lpTypeAttr != NULL) lpTypeInfo->ReleaseTypeAttr(lpTypeAttr); if (lpTypeInfo != NULL) lpTypeInfo->Release(); if (ptlib != NULL) ptlib->Release(); return hr; } HRESULT CDLDupWStr( LPWSTR *pszwstrDst, LPCWSTR szwSrc ) { HRESULT hr = S_OK; *pszwstrDst = new WCHAR[lstrlenW(szwSrc)+1]; if (*pszwstrDst) StrCpyW( *pszwstrDst, szwSrc ); else hr = E_OUTOFMEMORY; return hr; } extern CMutexSem g_mxsCodeDownloadGlobals; HRESULT MakeUniqueTempDirectory(LPCSTR szTempDir, LPSTR szUniqueTempDir, int iLen) { int n = 1; HRESULT hr = S_OK; //execute entire function under critical section CLock lck(g_mxsCodeDownloadGlobals); do { if (n > 100) // avoid infinite loop! break; wnsprintf(szUniqueTempDir, iLen-1, "%s%s%d.tmp", szTempDir, "ICD", n++); } while (GetFileAttributes(szUniqueTempDir) != -1); if (!CreateDirectory(szUniqueTempDir, NULL)) { hr = HRESULT_FROM_WIN32(GetLastError()); } return hr; } HRESULT ComposeHackClsidFromMime(LPSTR szHackMimeType, int iLen, LPCSTR szClsid) { HRESULT hr = S_OK; char szID[MAX_PATH]; LPSTR pchDest = szID; for (LPCSTR pchSrc = szClsid; *pchDest = *pchSrc; pchSrc++,pchDest++) { if (*pchSrc == '/') { *pchDest++ = '_'; *pchDest++ = '2'; *pchDest++ = 'F'; *pchDest = '_'; } } wnsprintf(szHackMimeType, iLen-1, "&CLSID=%s", szID); return hr; } HRESULT RemoveDirectoryAndChildren(LPCSTR szDir) { HRESULT hr = S_OK; HANDLE hf = INVALID_HANDLE_VALUE; char szBuf[MAX_PATH]; WIN32_FIND_DATA fd; if (RemoveDirectory(szDir)) goto Exit; // ha! we have a case where the directory is probbaly not empty StrNCpy(szBuf, szDir, sizeof(szBuf)); StrCatBuff(szBuf, "\\*", sizeof(szBuf)); if ((hf = FindFirstFile(szBuf, &fd)) == INVALID_HANDLE_VALUE) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } do { if ( (lstrcmp(fd.cFileName, ".") == 0) || (lstrcmp(fd.cFileName, "..") == 0)) continue; wnsprintf(szBuf, sizeof(szBuf)-1, "%s\\%s", szDir, fd.cFileName); if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { SetFileAttributes(szBuf, FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_NORMAL); if (FAILED((hr=RemoveDirectoryAndChildren(szBuf)))) { goto Exit; } } else { SetFileAttributes(szBuf, FILE_ATTRIBUTE_NORMAL); if (!DeleteFile(szBuf)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } } } while (FindNextFile(hf, &fd)); if (GetLastError() != ERROR_NO_MORE_FILES) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } if (hf != INVALID_HANDLE_VALUE) { FindClose(hf); hf = INVALID_HANDLE_VALUE; } // here if all subdirs/children removed /// re-attempt to remove the main dir if (!RemoveDirectory(szDir)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } Exit: if (hf != INVALID_HANDLE_VALUE) FindClose(hf); return hr; } HRESULT IsExtnHandled(LPSTR pszExt) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "IsExtnHandled", "%.80q", pszExt )); HRESULT hr = REGDB_E_CLASSNOTREG; HKEY hkRoot = HKEY_CLASSES_ROOT; char szFileExt[MAX_PATH]; DWORD cbFileExt = sizeof(szFileExt); char szCmdLine[2*MAX_PATH]; char szProgID[2*MAX_PATH]; LONG cbProgID = sizeof(szProgID); DWORD dwType; DWORD dwLen = sizeof(szCmdLine); HKEY hkeyCmd = 0; if (pszExt[0] == '\0') { goto Exit; } StrNCpy(szFileExt,pszExt, sizeof(szFileExt)); Assert((szFileExt[0] == '.')); // the entry begins with '.' so it may be a file extension // query the value (which is the ProgID) if (RegQueryValue(hkRoot, szFileExt, szProgID, &cbProgID) == ERROR_SUCCESS) { // we got the value (ProgID), now query for the CLSID // string and convert it to a CLSID StrCatBuff(szProgID, "\\Shell\\Open\\Command", sizeof(szProgID)); if ( (RegOpenKeyEx(HKEY_CLASSES_ROOT, szProgID, 0, KEY_QUERY_VALUE, &hkeyCmd) == ERROR_SUCCESS) && (SHQueryValueEx(hkeyCmd, NULL, NULL, &dwType, &szCmdLine, &dwLen) == ERROR_SUCCESS) && dwLen) { if (GetEXEName(szCmdLine)) { hr = S_OK; } } } Exit: if (hkeyCmd) RegCloseKey(hkeyCmd); DEBUG_LEAVE(hr); return hr; } #define SZMIMESIZE_MAX 128 HRESULT IsMimeHandled(LPCWSTR pwszMime) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "IsMimeHandled", "%.80wq", pwszMime )); HRESULT hr = S_OK; HKEY hMimeKey = NULL; DWORD dwType; char szValue[MAX_PATH]; DWORD dwValueLen = MAX_PATH; static char szMimeKey[] = "MIME\\Database\\Content Type\\"; static char szExtension[] = "Extension"; const ULONG ulMimeKeyLen = ((sizeof(szMimeKey)/sizeof(char))-1); char szKey[SZMIMESIZE_MAX + ulMimeKeyLen]; LPSTR pszMime = NULL; if (SUCCEEDED((hr=::Unicode2Ansi(pwszMime, &pszMime)))) { StrNCpy(szKey, szMimeKey, sizeof(szKey)); StrCatBuff(szKey, pszMime, sizeof(szKey)); hr = REGDB_E_READREGDB; if (RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_QUERY_VALUE, &hMimeKey) == ERROR_SUCCESS) { if (RegQueryValueEx(hMimeKey , szExtension , NULL , &dwType , (LPBYTE)szValue , &dwValueLen) == ERROR_SUCCESS) { hr = IsExtnHandled(szValue); } } } if (hMimeKey) { RegCloseKey(hMimeKey); } SAFEDELETE(pszMime); DEBUG_LEAVE(hr); return hr; }