?? divfile.cpp
字號:
//======================================================================
// DivFile - A Windows CE file filter DLL
//
// Written for the book Programming Windows CE
// Copyright (C) 1998 Douglas Boling
//======================================================================
#include <windows.h> // For all that Windows stuff
#define INITGUID
#include <initguid.h> // GUID defines
#include <replfilt.h> // Required for file filters
#include <rapi.h> // Required for RAPI functions
#include "DivFile.h"
HINSTANCE hInst; // DLL instance handle
long g_DllCnt = 0; // Global DLL reference count
// Replace this GUID with your own!
// {2B06F7A1-088E-11d2-93F1-204C4F4F5020}
static const GUID CLSID_MyCopyFilter =
{0x2b06f7a1, 0x88e, 0x11d2, {0x93,0xf1,0x20,0x4c,0x4f,0x4f,0x50,0x20}};
//======================================================================
// DllMain - DLL initialization entry point
//
BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD dwReason,
LPVOID lpvReserved) {
hInst = hinstDLL;
return TRUE;
}
//======================================================================
// DllGetClassObject - Exported function called to get pointer to
// Class factory object
//
STDAPI DllGetClassObject (REFCLSID rclsid, REFIID riid, LPVOID *ppv) {
MyClassFactory *pcf;
HRESULT hr;
// See if caller wants us....
if (IsEqualCLSID (rclsid, CLSID_MyCopyFilter)) {
// Create class factory object.
pcf = new MyClassFactory();
if (pcf == NULL)
return E_OUTOFMEMORY;
// Call class factory's query interface method.
hr = pcf->QueryInterface (riid, ppv);
// This will cause an object delete unless interface found.
pcf->Release();
return hr;
}
return CLASS_E_CLASSNOTAVAILABLE;
}
//======================================================================
// DllCanUnloadNow - Exported function called when DLL can unload
//
STDAPI DllCanUnloadNow () {
if (g_DllCnt)
return S_FALSE;
return S_OK;
}
//**********************************************************************
// MyClassFactory Object implementation
//----------------------------------------------------------------------
// Object constructor
MyClassFactory::MyClassFactory () {
m_lRef = 1; // Set ref count to 1 on create.
g_DllCnt++;
return;
}
//----------------------------------------------------------------------
// Object destructor
MyClassFactory::~MyClassFactory () {
g_DllCnt--;
return;
}
//----------------------------------------------------------------------
// QueryInterface - Called to see what interfaces this object supports
STDMETHODIMP MyClassFactory::QueryInterface (THIS_ REFIID riid,
LPVOID *ppv) {
// If caller wants our IUnknown or IClassFactory object,
// return a pointer to the object.
if (IsEqualIID (riid, IID_IUnknown) ||
IsEqualIID (riid, IID_IClassFactory)){
*ppv = (IClassFactory *)this; // Return pointer to object.
AddRef(); // Inc ref to prevent delete on return.
return NOERROR;
}
*ppv = NULL;
return (E_NOINTERFACE);
}
//----------------------------------------------------------------------
// AddRef - Increment object ref count.
STDMETHODIMP_(ULONG) MyClassFactory::AddRef (THIS) {
ULONG cnt;
cnt = (ULONG)InterlockedIncrement (&m_lRef);
return cnt;
}
//----------------------------------------------------------------------
// Release - Decrement object ref count.
STDMETHODIMP_(ULONG) MyClassFactory::Release (THIS) {
ULONG cnt;
cnt = (ULONG)InterlockedDecrement (&m_lRef);
if (cnt == 0) {
delete this;
return 0;
}
return cnt;
}
//----------------------------------------------------------------------
// LockServer - Called to tell the DLL not to unload even if use cnt 0
STDMETHODIMP MyClassFactory::LockServer (BOOL fLock) {
if (fLock)
InterlockedIncrement (&g_DllCnt);
else
InterlockedDecrement (&g_DllCnt);
return NOERROR;
}
//----------------------------------------------------------------------
// CreateInstance - Called to have class factory object create other
// objects
STDMETHODIMP MyClassFactory::CreateInstance (LPUNKNOWN pUnkOuter,
REFIID riid,
LPVOID *ppv) {
MyFileFilter *pMyff;
HRESULT hr;
if (pUnkOuter)
return (CLASS_E_NOAGGREGATION);
if (IsEqualIID (riid, IID_IUnknown) ||
IsEqualIID (riid, IID_ICeFileFilter)) {
// Create file filter object.
pMyff = new MyFileFilter();
if (!pMyff)
return E_OUTOFMEMORY;
// See if object exports the proper interface.
hr = pMyff->QueryInterface (riid, ppv);
// This will cause an object delete unless interface found.
pMyff->Release ();
return hr;
}
return E_NOINTERFACE;
}
//**********************************************************************
// MyFileFilter Object implementation
//----------------------------------------------------------------------
// Object constructor
MyFileFilter::MyFileFilter () {
m_lRef = 1; // Set ref count to 1 on create.
return;
}
//----------------------------------------------------------------------
// Object destructor
MyFileFilter::~MyFileFilter () {
return;
}
//----------------------------------------------------------------------
// QueryInterface - Called to see what interfaces this object supports
STDMETHODIMP MyFileFilter::QueryInterface (THIS_ REFIID riid,
LPVOID *ppv) {
// If caller wants our IUnknown or IID_ICeFileFilter object,
// return a pointer to the object.
if (IsEqualIID (riid, IID_IUnknown) ||
IsEqualIID (riid, IID_ICeFileFilter)){
// Return pointer to object.
*ppv = (ICeFileFilter *)this;
AddRef(); // Inc ref to prevent delete on return.
return NOERROR;
}
*ppv = NULL;
return (E_NOINTERFACE);
}
//----------------------------------------------------------------------
// AddRef - Increment object ref count.
STDMETHODIMP_(ULONG) MyFileFilter::AddRef (THIS) {
ULONG cnt;
cnt = (ULONG)InterlockedIncrement (&m_lRef);
return cnt;
}
//----------------------------------------------------------------------
// Release - Decrement object ref count.
STDMETHODIMP_(ULONG) MyFileFilter::Release (THIS) {
ULONG cnt;
cnt = (ULONG)InterlockedDecrement (&m_lRef);
if (cnt == 0)
delete this;
return cnt;
}
//----------------------------------------------------------------------
// NextConvertFile - Called to convert the next file
STDMETHODIMP MyFileFilter::NextConvertFile (int nConversion,
CFF_CONVERTINFO *pci, CFF_SOURCEFILE *psf,
CFF_DESTINATIONFILE *pdf,
volatile BOOL *pbCancel, CF_ERROR *perr) {
IStream *pstreamSrc;
IStream *pstreamDest;
ICeFileFilterSite *pffs;
CEOSVERSIONINFO vi;
DWORD cBytesRemaining, cBytesRead, cCopySize;
LARGE_INTEGER largMov;
TCHAR szNewName[MAX_PATH];
PBYTE pBuff;
HRESULT hr;
int i;
// If first call for file, see if too large to fit in object store.
if (nConversion == 0) {
m_fBreakFile = FALSE;
m_ulTotalMoved = 0;
// If import to CE and file > 4 MB, see if too big for
// object store.
if ((pci->bImport) && psf->cbSize > FILESIZELIMIT) {
vi.dwOSVersionInfoSize = sizeof (vi);
CeGetVersionEx (&vi);
// If version < 2.1, ask user
// if we should break file.
i = (vi.dwMajorVersion << 8) | vi.dwMinorVersion;
if (i < 0x20a) {
i = MessageBox (pci->hwndParent,
TEXT ("The file being copied is too \
large for the object store, would you like to break it into separate \
files?"),
TEXT ("Size Filter"), MB_YESNO);
if (i == IDYES)
m_fBreakFile = TRUE;
else {
*perr = HRESULT_TO_PFERROR (hr,ERROR_ACCESS_DENIED);
return E_FAIL;
}
}
}
} else if (m_fBreakFile) {
if ((UINT)(nConversion * FILEBREAKSIZE) > psf->cbSize)
return HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
} else
return HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
// Allocate buffer for transfer.
pBuff = (PBYTE)LocalAlloc (LPTR, BUFFSIZE);
if (!pBuff) {
*perr = HRESULT_TO_PFERROR (hr, E_OUTOFMEMORY);
return E_FAIL;
}
// Get pointer to FileFilterSite interface.
pffs = pci->pffs;
// Open source file.
hr = pffs->OpenSourceFile (PF_OPENFLAT, (PVOID *)&pstreamSrc);
if (!SUCCEEDED (hr)) {
LocalFree (pBuff);
*perr = HRESULT_TO_PFERROR (hr, ERROR_ACCESS_DENIED);
return E_FAIL;
}
// Seek to part of file for this section.
if (m_fBreakFile) {
largMov.HighPart = 0;
largMov.LowPart = nConversion * FILEBREAKSIZE;
hr = pstreamSrc->Seek (largMov, STREAM_SEEK_SET, NULL);
// Modify destination name to mark part. New name becomes
// old name with a number appended for each part.
wsprintf (szNewName, TEXT ("%s%s_%d.%s"),
pdf->szPath, pdf->szFilename, nConversion,
pdf->szExtension);
hr = pffs->OpenDestinationFile (PF_OPENFLAT, szNewName,
(PVOID *)&pstreamDest);
if (!SUCCEEDED (hr)) {
LocalFree (pBuff);
pffs->CloseSourceFile (pstreamSrc);
*perr = HRESULT_TO_PFERROR (hr, ERROR_ACCESS_DENIED);
return E_FAIL;
}
} else
// Open destination file with default name.
hr = pffs->OpenDestinationFile (PF_OPENFLAT, NULL,
(PVOID *)&pstreamDest);
if (!SUCCEEDED (hr)) {
LocalFree (pBuff);
pffs->CloseSourceFile (pstreamSrc);
*perr = HRESULT_TO_PFERROR (hr, ERROR_ACCESS_DENIED);
return E_FAIL;
}
// Copy data.
cCopySize = min (psf->cbSize - m_ulTotalMoved, FILEBREAKSIZE);
for (cBytesRemaining = cCopySize; cBytesRemaining > 0; ) {
// Read the data.
i = min (BUFFSIZE, cBytesRemaining);
hr = pstreamSrc->Read (pBuff, i, &cBytesRead);
if (cBytesRead == 0)
break;
// See if user canceled the transfer.
if (*pbCancel) {
hr = ERROR_CANCELLED;
break;
}
// Write the data and update bytes remaining.
hr = pstreamDest->Write (pBuff, cBytesRead, NULL);
if (!SUCCEEDED (hr))
break;
// Update transfer totals.
m_ulTotalMoved += cBytesRead;
cBytesRemaining -= cBytesRead;
// Tell the user how far we've gotten.
pffs->ReportProgress (m_ulTotalMoved/psf->cbSize * 100);
}
// Close files and clean up.
pffs->CloseSourceFile (pstreamSrc);
pffs->CloseDestinationFile (TRUE, pstreamDest);
LocalFree (pBuff);
if (hr == ERROR_CANCELLED)
return HRESULT_FROM_WIN32 (ERROR_CANCELLED);
if (!SUCCEEDED (hr)) {
*perr = hr;
return E_FAIL;
}
return NOERROR;
}
//----------------------------------------------------------------------
// FilterOptions - Called to indicate the file filter options
STDMETHODIMP MyFileFilter::FilterOptions (HWND hwndParent) {
MessageBox (hwndParent, TEXT ("Filter Options Box"), TEXT ("Title"),
MB_OK);
return NOERROR;
}
//----------------------------------------------------------------------
// FormatMessage - Called to format error messages
//
STDMETHODIMP MyFileFilter::FormatMessage (DWORD dwFlags,
DWORD dwMessageId, DWORD dwLanguageId,
LPTSTR lpBuffer, DWORD dwSize,
va_list *args, DWORD *pcb) {
DWORD cMsgLen;
// Pass the error code on to the Win32 FormatMessage. Force look
// into message table of filter by ORing dwFlags with
// FORMAT_MESSAGE_FROM_HMODULE.
cMsgLen = ::FormatMessage (dwFlags | FORMAT_MESSAGE_FROM_HMODULE,
hInst, dwMessageId, dwLanguageId,
lpBuffer, dwSize, args);
if (cMsgLen)
*pcb = cMsgLen;
else
return E_FAIL;
return NOERROR;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -