NT4/private/ole32/com/inc/exttbl.cxx
2020-09-30 17:12:29 +02:00

246 lines
6.7 KiB
C++

//+---------------------------------------------------------------------------//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1993 - 1993.
//
// File: exttbl.cxx
//
// Contents: File extension to CLSID cache
//
// Classes: CFileExtTbl
// CScmFileExtTbl
//
// Functions: none
//
// History: 20-May-94 Rickhi Created
// 20-Feb-95 BruceMa Don't include file extension unless
// CLSID is valid
//
//----------------------------------------------------------------------------
#include <ole2int.h>
#include <exttbl.hxx>
//+-------------------------------------------------------------------------
//
// member: CFileExtTbl::FindClassExt
//
// Synopsis: Finds the clsid that maps to the given file extension
//
// Arguments: [pszExt] - the file extension to look up
// [pclsid] - where to return the clsid
//
// Returns: S_OK if found
// REGDB_E_CLASSNOTREG if not found
//
//--------------------------------------------------------------------------
HRESULT CFileExtTbl::FindClassExt(LPCWSTR pszExt, CLSID *pClsid)
{
// lower case the entry so that searches can be case sensitive
// (faster than case insensitive searches).
WCHAR wszExt[MAX_PATH];
lstrcpyW(wszExt, pszExt);
CharLowerW(wszExt);
Win4Assert(_pStart && "CFileExtTbl not initialized");
BYTE *pEntry = _pStart;
BYTE *pEnd = _pStart + (_pTblHdr->OffsEnd - _pTblHdr->OffsStart);
while (pEntry < pEnd)
{
// compare the class extensions
if (!lstrcmpW(wszExt, ((SExtEntry *)pEntry)->wszExt))
{
// found a match, we're done
memcpy(pClsid, &((SExtEntry *)pEntry)->Clsid, sizeof(CLSID));
return S_OK;
}
Win4Assert((((SExtEntry *)pEntry)->ulEntryLen & 0x07) == 0);
pEntry += ((SExtEntry *)pEntry)->ulEntryLen;
}
return REGDB_E_CLASSNOTREG;
}
//+-------------------------------------------------------------------------
//
// member: CScmFileExtTbl::InitTbl
//
// Synopsis: creates a local memory copy of the file extension to CLSID
// mapping table.
//
// Arguments: [pulSize] - where to return the size of the generated table
//
// Returns: S_OK if successful
// E_OUTOFMEMORY if no memory
//
//--------------------------------------------------------------------------
HRESULT CScmFileExtTbl::InitTbl(ULONG *pulSize)
{
// init size to zero
*pulSize = 0;
// allocate local memory in which to build the table
_pLocTbl = (SExtTblHdr *) PrivMemAlloc(EXTTBL_MAX_SIZE);
if (!_pLocTbl)
{
return E_OUTOFMEMORY;
}
// initialize the table header
_pLocTbl->ulSize = EXTTBL_MAX_SIZE;
_pLocTbl->cEntries = 0;
_pLocTbl->OffsStart = sizeof(SExtTblHdr);
_pLocTbl->OffsEnd = sizeof(SExtTblHdr);
// build the table from the data in the registry
// enumerate the entries under the key
HKEY hkRoot = HKEY_CLASSES_ROOT;
DWORD iFileExt = 0;
FILETIME ftLastWrite;
WCHAR szFileExt[MAX_PATH];
DWORD cbFileExt = sizeof(szFileExt);
while (RegEnumKeyEx(hkRoot, iFileExt, szFileExt, &cbFileExt,
NULL, NULL, NULL, &ftLastWrite)== ERROR_SUCCESS)
{
if (szFileExt[0] == L'.')
{
// the entry begins with '.' so it may be a file extension
// query the value (which is the ProgID)
WCHAR szProgID[MAX_PATH];
LONG cbProgID = sizeof(szProgID);
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
WCHAR szClsid[40];
LONG cbClsid = sizeof(szClsid);
lstrcatW(szProgID, L"\\Clsid");
if (RegQueryValue(HKEY_CLASSES_ROOT, szProgID, szClsid,
&cbClsid) == ERROR_SUCCESS)
{
// make sure the clsid is valid
cbProgID = sizeof(szProgID);
WCHAR szClsidEntry[80];
lstrcpyW(szClsidEntry, L"Clsid\\");
lstrcatW(szClsidEntry, szClsid);
if (RegQueryValue(HKEY_CLASSES_ROOT, szClsidEntry,
szProgID, &cbProgID) == ERROR_SUCCESS)
{
CLSID clsid;
// Don't add file extension unless CLSID is valid
if (GUIDFromString(szClsid, &clsid))
{
Add(szFileExt, &clsid);
}
}
}
}
}
++iFileExt;
cbFileExt = sizeof(szFileExt);
}
// update the table size to the combined size of all the entries
// we generated above, and return this size to the caller.
_pLocTbl->ulSize = _pLocTbl->OffsEnd;
*pulSize = _pLocTbl->ulSize;
return S_OK;
}
//+-------------------------------------------------------------------------
//
// member: CScmFileExtTbl::Add
//
// Synopsis: creates a cache node and adds it to the table.
//
// Arguments: [pszExt] - the file extension to look up
// [pClsid] - where to return the clsid
//
// Returns: S_OK if successfull,
// REG error otherwise
//
//--------------------------------------------------------------------------
HRESULT CScmFileExtTbl::Add(LPCWSTR pwszExt, CLSID *pClsid)
{
// lower case the entry so that searches can be case sensitive
// (faster than case insensitive searches).
WCHAR wszExt[MAX_PATH];
lstrcpyW(wszExt, pwszExt);
CharLowerW(wszExt);
// compute how much space we need for this entry. Note that the
// terminating NULL is accounted for in the sizeof(SExtEntry).
// we also keep the structures 8 byte aligned.
ULONG ulStrLen = lstrlenW(wszExt) * sizeof(WCHAR);
ULONG ulEntryLen = (sizeof(SExtEntry) + ulStrLen + 7) & 0xfffffff8;
// make sure this entry will fit in the currently allocated block.
if (_pLocTbl->OffsEnd + ulEntryLen <= _pLocTbl->ulSize)
{
// copy in the guid and the extension
SExtEntry *pEntry = (SExtEntry *)((BYTE *)_pLocTbl + _pLocTbl->OffsEnd);
memcpy(&pEntry->Clsid, pClsid, sizeof(CLSID));
memcpy(&pEntry->wszExt, wszExt, ulStrLen + sizeof(WCHAR));
pEntry->ulEntryLen = ulEntryLen;
// update the ending offset
_pLocTbl->OffsEnd += ulEntryLen;
return S_OK;
}
// could not fit this entry in the table
return E_OUTOFMEMORY;
}
//+-------------------------------------------------------------------------
//
// member: CScmExtTbl::CopyTbl
//
// Synopsis: copies the locally-built table to shared memory
//
// Arguments: [pShrTbl] - ptr to shared memory table
//
// Returns: nothing
//
//--------------------------------------------------------------------------
BYTE *CScmFileExtTbl::CopyTbl(BYTE *pShrTbl)
{
BYTE *pEnd = pShrTbl;
if (_pLocTbl != NULL)
{
// now that we have built a local memory copy of the table, copy
// the table into shared memory.
memcpy(pShrTbl, (BYTE *)_pLocTbl, _pLocTbl->ulSize);
pEnd += _pLocTbl->ulSize;
}
return pEnd;
}