You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1857 lines
41 KiB
1857 lines
41 KiB
//
|
|
// Microsoft Windows Media Technologies
|
|
// Copyright (C) Microsoft Corporation, 1999 - 2001. All rights reserved.
|
|
//
|
|
|
|
// MSHDSP.DLL is a sample WMDM Service Provider(SP) that enumerates fixed drives.
|
|
// This sample shows you how to implement an SP according to the WMDM documentation.
|
|
// This sample uses fixed drives on your PC to emulate portable media, and
|
|
// shows the relationship between different interfaces and objects. Each hard disk
|
|
// volume is enumerated as a device and directories and files are enumerated as
|
|
// Storage objects under respective devices. You can copy non-SDMI compliant content
|
|
// to any device that this SP enumerates. To copy an SDMI compliant content to a
|
|
// device, the device must be able to report a hardware embedded serial number.
|
|
// Hard disks do not have such serial numbers.
|
|
//
|
|
// To build this SP, you are recommended to use the MSHDSP.DSP file under Microsoft
|
|
// Visual C++ 6.0 and run REGSVR32.EXE to register the resulting MSHDSP.DLL. You can
|
|
// then build the sample application from the WMDMAPP directory to see how it gets
|
|
// loaded by the application. However, you need to obtain a certificate from
|
|
// Microsoft to actually run this SP. This certificate would be in the KEY.C file
|
|
// under the INCLUDE directory for one level up.
|
|
|
|
|
|
// MDSPStorage.cpp : Implementation of CMDSPStorage
|
|
|
|
#include "hdspPCH.h"
|
|
#include "wmsstd.h"
|
|
#define STRSAFE_NO_DEPRECATE
|
|
#include "strsafe.h"
|
|
|
|
|
|
#define CONEg(p)\
|
|
do\
|
|
{\
|
|
if (!(p))\
|
|
{\
|
|
hr = WMDM_E_INTERFACEDEAD;\
|
|
goto Error;\
|
|
}\
|
|
}\
|
|
while (fFalse)
|
|
|
|
typedef struct __MOVETHREADARGS
|
|
{
|
|
WCHAR wcsSrc[MAX_PATH];
|
|
WCHAR wcsDst[MAX_PATH];
|
|
BOOL bNewThread;
|
|
IWMDMProgress *pProgress;
|
|
LPSTREAM pStream;
|
|
CMDSPStorage *pThis;
|
|
DWORD dwStatus;
|
|
|
|
} MOVETHREADARGS;
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CMDSPStorage
|
|
CMDSPStorage::CMDSPStorage()
|
|
{
|
|
m_hFile = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
CMDSPStorage::~CMDSPStorage()
|
|
{
|
|
if( m_hFile != INVALID_HANDLE_VALUE )
|
|
{
|
|
CloseHandle(m_hFile);
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP CMDSPStorage::GetStorageGlobals(IMDSPStorageGlobals **ppStorageGlobals)
|
|
{
|
|
HRESULT hr;
|
|
int i;
|
|
BOOL bLocked = 0;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
g_CriticalSection.Lock();
|
|
bLocked = 1;
|
|
|
|
CARg(ppStorageGlobals);
|
|
CONEg(m_wcsName[0]);
|
|
|
|
WCHAR devName[MAX_PATH], *pW;
|
|
pW = &devName[0];
|
|
hr = wcsParseDeviceName(m_wcsName, pW, ARRAYSIZE(devName));
|
|
if (FAILED(hr))
|
|
{
|
|
goto Error;
|
|
}
|
|
|
|
for(i=0; i<MDSP_MAX_DEVICE_OBJ;i++)
|
|
{
|
|
if( !wcscmp(g_GlobalDeviceInfo[i].wcsDevName, devName) )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( i<MDSP_MAX_DEVICE_OBJ && g_GlobalDeviceInfo[i].pIMDSPStorageGlobals ) // found match
|
|
{
|
|
*ppStorageGlobals = (IMDSPStorageGlobals *)g_GlobalDeviceInfo[i].pIMDSPStorageGlobals;
|
|
((IMDSPStorageGlobals *)g_GlobalDeviceInfo[i].pIMDSPStorageGlobals)->AddRef();
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{ // new entry in the global array
|
|
if(!(i<MDSP_MAX_DEVICE_OBJ) ) // no match found
|
|
{
|
|
for(i=0; i<MDSP_MAX_DEVICE_OBJ;i++)
|
|
{
|
|
if( !g_GlobalDeviceInfo[i].bValid )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
CPRg(i<MDSP_MAX_DEVICE_OBJ);
|
|
|
|
CComObject<CMDSPStorageGlobals> *pObj;
|
|
CORg(CComObject<CMDSPStorageGlobals>::CreateInstance(&pObj));
|
|
hr = pObj->QueryInterface(
|
|
IID_IMDSPStorageGlobals,
|
|
reinterpret_cast<void**>(&g_GlobalDeviceInfo[i].pIMDSPStorageGlobals)
|
|
);
|
|
if( FAILED(hr) )
|
|
{
|
|
delete pObj;
|
|
}
|
|
else
|
|
{
|
|
HRESULT hrTemp;
|
|
|
|
// wcscpy(pObj->m_wcsName, devName);
|
|
hrTemp = StringCchCopyW(pObj->m_wcsName, ARRAYSIZE(pObj->m_wcsName), devName);
|
|
if (FAILED(hrTemp))
|
|
{
|
|
((IUnknown*) (g_GlobalDeviceInfo[i].pIMDSPStorageGlobals))->Release();
|
|
g_GlobalDeviceInfo[i].pIMDSPStorageGlobals = NULL;
|
|
hr = hrTemp;
|
|
goto Error;
|
|
}
|
|
|
|
// wcscpy(g_GlobalDeviceInfo[i].wcsDevName, devName);
|
|
hrTemp = StringCchCopyW(g_GlobalDeviceInfo[i].wcsDevName,
|
|
ARRAYSIZE(g_GlobalDeviceInfo[i].wcsDevName), devName);
|
|
if (FAILED(hrTemp))
|
|
{
|
|
((IUnknown*) (g_GlobalDeviceInfo[i].pIMDSPStorageGlobals))->Release();
|
|
g_GlobalDeviceInfo[i].pIMDSPStorageGlobals = NULL;
|
|
g_GlobalDeviceInfo[i].wcsDevName[0] = 0;
|
|
hr = hrTemp;
|
|
goto Error;
|
|
}
|
|
*ppStorageGlobals = (IMDSPStorageGlobals *)g_GlobalDeviceInfo[i].pIMDSPStorageGlobals;
|
|
g_GlobalDeviceInfo[i].bValid=TRUE;
|
|
g_GlobalDeviceInfo[i].dwStatus = 0;
|
|
} // end of else
|
|
} // end of else
|
|
|
|
Error:
|
|
|
|
if (bLocked)
|
|
{
|
|
g_CriticalSection.Unlock();
|
|
}
|
|
|
|
hrLogDWORD("IMSDPStorage::GetStorageGlobals returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::SetAttributes(DWORD dwAttributes, _WAVEFORMATEX *pFormat)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
DWORD dwAttrib;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
CONEg(m_wcsName[0]);
|
|
|
|
WideCharToMultiByte(CP_ACP, NULL, m_wcsName, -1, m_szTmp, MAX_PATH, NULL, NULL);
|
|
|
|
dwAttrib = GetFileAttributesA(m_szTmp);
|
|
|
|
if( dwAttrib == (DWORD)0xFFFFFFFF )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
if( (dwAttributes & WMDM_FILE_ATTR_READONLY) )
|
|
{
|
|
dwAttrib |= FILE_ATTRIBUTE_READONLY;
|
|
}
|
|
|
|
if( (dwAttributes & WMDM_FILE_ATTR_HIDDEN) )
|
|
{
|
|
dwAttrib |= FILE_ATTRIBUTE_HIDDEN;
|
|
}
|
|
|
|
if( (dwAttributes & WMDM_FILE_ATTR_SYSTEM) )
|
|
{
|
|
dwAttrib |= FILE_ATTRIBUTE_SYSTEM;
|
|
}
|
|
|
|
CWRg(SetFileAttributesA(m_szTmp, dwAttrib));
|
|
|
|
hr = S_OK;
|
|
|
|
Error:
|
|
|
|
hrLogDWORD("IMSDPStorage::SetAttributes returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT QuerySubFoldersAndFiles(LPCSTR szCurrentFolder, DWORD *pdwAttr)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
LPSTR szName = NULL;
|
|
int len;
|
|
WIN32_FIND_DATAA fd;
|
|
int nErrorEnd=0;
|
|
HANDLE hFFile = INVALID_HANDLE_VALUE;
|
|
DWORD dwAttrib;
|
|
|
|
CARg(szCurrentFolder);
|
|
CARg(pdwAttr);
|
|
|
|
len = strlen(szCurrentFolder);
|
|
CARg(len>2);
|
|
|
|
szName = new char [len+BACKSLASH_SZ_STRING_LENGTH+MAX_PATH];
|
|
CPRg(szName);
|
|
|
|
strcpy(szName, szCurrentFolder);
|
|
if( szName[strlen(szName)-1] != 0x5c )
|
|
{
|
|
strcat(szName, g_szBackslash);
|
|
}
|
|
strcat(szName, "*");
|
|
|
|
while( !nErrorEnd )
|
|
{
|
|
if( hFFile == INVALID_HANDLE_VALUE )
|
|
{
|
|
hFFile = FindFirstFileA(szName, &fd);
|
|
if( hFFile == INVALID_HANDLE_VALUE )
|
|
{
|
|
nErrorEnd = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( !FindNextFileA(hFFile, &fd) )
|
|
{
|
|
nErrorEnd = 1;
|
|
}
|
|
}
|
|
|
|
if ( !nErrorEnd && hFFile != INVALID_HANDLE_VALUE )
|
|
{
|
|
if( !strcmp(fd.cFileName, ".") || !strcmp(fd.cFileName, "..") )
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
strcpy(szName, szCurrentFolder);
|
|
if( szName[strlen(szName)-1] != 0x5c ) strcat(szName, g_szBackslash);
|
|
strcat(szName, fd.cFileName);
|
|
dwAttrib = GetFileAttributesA(szName);
|
|
if( dwAttrib & FILE_ATTRIBUTE_DIRECTORY )
|
|
{
|
|
*pdwAttr |= WMDM_STORAGE_ATTR_HAS_FOLDERS;
|
|
}
|
|
else
|
|
{
|
|
*pdwAttr |= WMDM_STORAGE_ATTR_HAS_FILES;
|
|
}
|
|
if( (*pdwAttr & WMDM_STORAGE_ATTR_HAS_FOLDERS) &&
|
|
(*pdwAttr & WMDM_STORAGE_ATTR_HAS_FILES ) )
|
|
{
|
|
break; // No need to continue since we found both
|
|
}
|
|
}
|
|
} // End of If
|
|
} // End of while
|
|
|
|
hr = S_OK;
|
|
|
|
Error:
|
|
|
|
if( hFFile != INVALID_HANDLE_VALUE )
|
|
{
|
|
FindClose(hFFile);
|
|
}
|
|
if( szName )
|
|
{
|
|
delete [] szName;
|
|
}
|
|
|
|
return hr; // If FAILED(hr), sorry, can't do it.
|
|
}
|
|
|
|
|
|
STDMETHODIMP CMDSPStorage::GetAttributes(DWORD * pdwAttributes, _WAVEFORMATEX * pFormat)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dwAttrib;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
CARg(pdwAttributes);
|
|
CONEg(m_wcsName[0]);
|
|
|
|
WideCharToMultiByte(CP_ACP, NULL, m_wcsName, -1, m_szTmp, MAX_PATH, NULL, NULL);
|
|
dwAttrib = GetFileAttributesA(m_szTmp);
|
|
|
|
if( dwAttrib == (DWORD)0xFFFFFFFF )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
*pdwAttributes = WMDM_STORAGE_ATTR_REMOVABLE |
|
|
WMDM_STORAGE_ATTR_FOLDERS |
|
|
WMDM_FILE_ATTR_CANREAD;
|
|
|
|
if( !(dwAttrib & FILE_ATTRIBUTE_READONLY) )
|
|
{
|
|
*pdwAttributes |= WMDM_FILE_ATTR_CANDELETE |
|
|
WMDM_FILE_ATTR_CANMOVE |
|
|
WMDM_FILE_ATTR_CANRENAME;
|
|
}
|
|
|
|
if( dwAttrib & FILE_ATTRIBUTE_DIRECTORY )
|
|
{
|
|
*pdwAttributes |= WMDM_FILE_ATTR_FOLDER;
|
|
|
|
QuerySubFoldersAndFiles(m_szTmp, pdwAttributes); // No failure check, if failed, just keep current attributes
|
|
}
|
|
else
|
|
{
|
|
*pdwAttributes |= WMDM_FILE_ATTR_FILE;
|
|
}
|
|
|
|
// Now handle Hidden, ReadOnly, and System attributes
|
|
if( (dwAttrib & FILE_ATTRIBUTE_READONLY) )
|
|
{
|
|
*pdwAttributes |= WMDM_FILE_ATTR_READONLY;
|
|
}
|
|
|
|
if( (dwAttrib & FILE_ATTRIBUTE_HIDDEN) )
|
|
{
|
|
*pdwAttributes |= WMDM_FILE_ATTR_HIDDEN;
|
|
}
|
|
|
|
if( (dwAttrib & FILE_ATTRIBUTE_SYSTEM) )
|
|
{
|
|
*pdwAttributes |= WMDM_FILE_ATTR_SYSTEM;
|
|
}
|
|
|
|
Error:
|
|
|
|
hrLogDWORD("IMSDPStorage::GetAttributes returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::GetName(LPWSTR pwszName, UINT nMaxChars)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
CONEg(m_wcsName[0]);
|
|
CARg(pwszName);
|
|
CPRg(wcslen(m_wcsName)<nMaxChars);
|
|
|
|
if( m_wcsName[wcslen(m_wcsName)-1] == 0x5c ) // this is root storage
|
|
{
|
|
wcscpy(pwszName, wcsrchr(m_wcsName, 0x5c));
|
|
}
|
|
else
|
|
{
|
|
wcscpy(pwszName, wcsrchr(m_wcsName, 0x5c)+1);
|
|
}
|
|
|
|
Error:
|
|
|
|
hrLogDWORD("IMSDPStorage::GetName returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP CMDSPStorage::GetDate(PWMDMDATETIME pDateTimeUTC)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
HANDLE hFFile = INVALID_HANDLE_VALUE;
|
|
WIN32_FIND_DATA wfd;
|
|
SYSTEMTIME sysTime;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
CARg(pDateTimeUTC);
|
|
CONEg(m_wcsName[0]);
|
|
|
|
CWRg(WideCharToMultiByte(CP_ACP, NULL, m_wcsName, -1, m_szTmp, MAX_PATH, NULL, NULL));
|
|
|
|
DWORD curAttr = GetFileAttributesA(m_szTmp);
|
|
if (curAttr == INVALID_FILE_ATTRIBUTES)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Error;
|
|
}
|
|
if( FILE_ATTRIBUTE_DIRECTORY & curAttr )
|
|
{
|
|
DWORD dwLen = strlen(m_szTmp)-1;
|
|
if( m_szTmp[dwLen-1] != 0x5c )
|
|
{
|
|
if (dwLen > ARRAYSIZE(m_szTmp) - 3)
|
|
{
|
|
hr = STRSAFE_E_INSUFFICIENT_BUFFER; // defined in strsafe.h
|
|
goto Error;
|
|
}
|
|
else
|
|
{
|
|
strcat(m_szTmp, g_szBackslash);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (dwLen > ARRAYSIZE(m_szTmp) - 2)
|
|
{
|
|
hr = STRSAFE_E_INSUFFICIENT_BUFFER; // defined in strsafe.h
|
|
goto Error;
|
|
}
|
|
}
|
|
strcat(m_szTmp, ".");
|
|
}
|
|
|
|
hFFile = FindFirstFile(m_szTmp, &wfd);
|
|
CWRg(hFFile != INVALID_HANDLE_VALUE);
|
|
|
|
CFRg(FileTimeToSystemTime((CONST FILETIME *)&wfd.ftLastWriteTime, &sysTime));
|
|
|
|
pDateTimeUTC->wYear = sysTime.wYear;
|
|
pDateTimeUTC->wMonth = sysTime.wMonth;
|
|
pDateTimeUTC->wDay = sysTime.wDay;
|
|
pDateTimeUTC->wHour = sysTime.wHour;
|
|
pDateTimeUTC->wMinute = sysTime.wMinute;
|
|
pDateTimeUTC->wSecond = sysTime.wSecond;
|
|
|
|
hr = S_OK;
|
|
|
|
Error:
|
|
|
|
if(hFFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
FindClose(hFFile);
|
|
}
|
|
|
|
hrLogDWORD("IMSDPStorage::GetDate returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::GetSize(DWORD * pdwSizeLow, DWORD * pdwSizeHigh)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
DWORD dwLS;
|
|
DWORD dwHS;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
CARg(pdwSizeLow);
|
|
CONEg(m_wcsName[0]);
|
|
|
|
CWRg(WideCharToMultiByte(CP_ACP, NULL, m_wcsName, -1, m_szTmp, MAX_PATH, NULL, NULL));
|
|
|
|
dwLS = 0;
|
|
dwHS = 0;
|
|
|
|
DWORD curAttr = GetFileAttributesA(m_szTmp);
|
|
if (curAttr == INVALID_FILE_ATTRIBUTES)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Error;
|
|
}
|
|
if( FILE_ATTRIBUTE_DIRECTORY & curAttr )
|
|
{
|
|
*pdwSizeLow = 0;
|
|
*pdwSizeHigh = 0;
|
|
}
|
|
else
|
|
{
|
|
CORg(GetFileSizeRecursive(m_szTmp, &dwLS, &dwHS));
|
|
*pdwSizeLow = dwLS;
|
|
if(pdwSizeHigh)
|
|
{
|
|
*pdwSizeHigh = dwHS;
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
Error:
|
|
|
|
hrLogDWORD("IMSDPStorage::GetSize returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::GetRights(PWMDMRIGHTS *ppRights,UINT *pnRightsCount,
|
|
BYTE abMac[WMDM_MAC_LENGTH])
|
|
{
|
|
HRESULT hr;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
CORg(WMDM_E_NOTSUPPORTED);
|
|
|
|
Error:
|
|
|
|
hrLogDWORD("IMSDPStorage::GetRights returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::CreateStorage(DWORD dwAttributes, _WAVEFORMATEX * pFormat, LPWSTR pwszName, IMDSPStorage * * ppNewStorage)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
HANDLE hFile;
|
|
CHAR *psz;
|
|
CHAR szNew[MAX_PATH];
|
|
DWORD curAttr = 0;
|
|
DWORD fsAttrib = FILE_ATTRIBUTE_NORMAL;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
CONEg(m_wcsName[0]);
|
|
CARg(pwszName);
|
|
CARg(ppNewStorage);
|
|
|
|
CWRg(WideCharToMultiByte(CP_ACP, NULL, m_wcsName, -1, m_szTmp, MAX_PATH, NULL, NULL));
|
|
if( m_szTmp[strlen(m_szTmp)-1] == 0x5c )
|
|
{
|
|
m_szTmp[strlen(m_szTmp)-1] = NULL; // trim the last backslash;
|
|
}
|
|
|
|
curAttr = GetFileAttributesA(m_szTmp);
|
|
if (curAttr == INVALID_FILE_ATTRIBUTES)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Error;
|
|
}
|
|
if( !(curAttr & FILE_ATTRIBUTE_DIRECTORY ) ) // if current storage is a file
|
|
{
|
|
if( dwAttributes & WMDM_STORAGECONTROL_INSERTINTO )
|
|
{
|
|
CORg(WMDM_E_NOTSUPPORTED); // can't do InsertInto
|
|
}
|
|
else
|
|
{ // for file, the default is Before&After
|
|
psz = strrchr(m_szTmp, g_szBackslash[0]);
|
|
CFRg(psz);
|
|
}
|
|
}
|
|
else
|
|
{ // current storage is a dir
|
|
if( (dwAttributes & WMDM_STORAGECONTROL_INSERTBEFORE) ||
|
|
(dwAttributes & WMDM_STORAGECONTROL_INSERTAFTER) ) // before or after
|
|
{
|
|
psz=strrchr(m_szTmp, g_szBackslash[0]);
|
|
CFRg(psz);
|
|
}
|
|
else
|
|
{ // for dir, the default is InsertInto
|
|
psz=m_szTmp+strlen(m_szTmp);
|
|
}
|
|
}
|
|
|
|
CWRg(WideCharToMultiByte(CP_ACP, NULL, pwszName, -1, szNew, MAX_PATH, NULL, NULL));
|
|
|
|
// strcpy(psz, g_szBackslash);
|
|
HRESULT hrTemp = StringCchCopyA(psz, ARRAYSIZE(m_szTmp) - (psz - m_szTmp), g_szBackslash);
|
|
if (FAILED(hrTemp))
|
|
{
|
|
hr = hrTemp;
|
|
goto Error;
|
|
}
|
|
// strcat(psz, szNew);
|
|
hrTemp = StringCchCatA(psz, ARRAYSIZE(m_szTmp) - (psz - m_szTmp), szNew);
|
|
if (FAILED(hrTemp))
|
|
{
|
|
hr = hrTemp;
|
|
goto Error;
|
|
}
|
|
|
|
// Find what file system attribute the intend storage should be
|
|
if( dwAttributes & WMDM_FILE_ATTR_HIDDEN )
|
|
{
|
|
fsAttrib |= FILE_ATTRIBUTE_HIDDEN;
|
|
}
|
|
if( dwAttributes & WMDM_FILE_ATTR_SYSTEM )
|
|
{
|
|
fsAttrib |= FILE_ATTRIBUTE_SYSTEM;
|
|
}
|
|
if( dwAttributes & WMDM_FILE_ATTR_READONLY )
|
|
{
|
|
fsAttrib |= FILE_ATTRIBUTE_READONLY;
|
|
}
|
|
|
|
if( dwAttributes & WMDM_FILE_ATTR_FOLDER )
|
|
{
|
|
if(CreateDirectoryA(m_szTmp, NULL))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = GetLastError();
|
|
if( hr == ERROR_ALREADY_EXISTS )
|
|
{
|
|
if( dwAttributes & WMDM_FILE_CREATE_OVERWRITE )
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
goto Error;
|
|
}
|
|
}
|
|
|
|
if( S_OK == hr )
|
|
{
|
|
SetFileAttributes(m_szTmp, fsAttrib);
|
|
}
|
|
}
|
|
else if ( dwAttributes & WMDM_FILE_ATTR_FILE )
|
|
{
|
|
// If Overwrite is specified, use CREATE_ALWAYS
|
|
if( dwAttributes & WMDM_FILE_CREATE_OVERWRITE )
|
|
{
|
|
hFile = CreateFileA(
|
|
m_szTmp,
|
|
GENERIC_WRITE | GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
fsAttrib,
|
|
NULL
|
|
);
|
|
}
|
|
else
|
|
{
|
|
hFile = CreateFileA(
|
|
m_szTmp,
|
|
GENERIC_WRITE | GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
CREATE_NEW,
|
|
fsAttrib,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
CWRg(hFile != INVALID_HANDLE_VALUE);
|
|
CloseHandle(hFile);
|
|
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Error;
|
|
}
|
|
|
|
if( hr == S_OK )
|
|
{
|
|
CComObject<CMDSPStorage> *pObj;
|
|
CORg(CComObject<CMDSPStorage>::CreateInstance(&pObj));
|
|
|
|
hr = pObj->QueryInterface(
|
|
IID_IMDSPStorage,
|
|
reinterpret_cast<void**>(ppNewStorage)
|
|
);
|
|
if( FAILED(hr) )
|
|
{
|
|
delete pObj;
|
|
}
|
|
else
|
|
{
|
|
MultiByteToWideChar(CP_ACP, NULL, m_szTmp, -1, pObj->m_wcsName, MAX_PATH);
|
|
}
|
|
}
|
|
|
|
Error:
|
|
|
|
hrLogDWORD("IMSDPStorage::CreateStorage returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::SendOpaqueCommand(OPAQUECOMMAND *pCommand)
|
|
{
|
|
HRESULT hr = WMDM_E_NOTSUPPORTED;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
Error:
|
|
|
|
hrLogDWORD("IMSDPStorage::SendOpaqueCommand returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
// IMDSPStorage2
|
|
STDMETHODIMP CMDSPStorage::GetStorage(
|
|
LPCWSTR pszStorageName,
|
|
IMDSPStorage** ppStorage )
|
|
{
|
|
HRESULT hr;
|
|
HRESULT hrTemp;
|
|
WCHAR pwszFileName[MAX_PATH];
|
|
DWORD dwAttrib;
|
|
CComObject<CMDSPStorage> *pStg = NULL;
|
|
|
|
// This storage need to be a folder to contain other storages.
|
|
WideCharToMultiByte(CP_ACP, NULL, m_wcsName, -1, m_szTmp, MAX_PATH, NULL, NULL);
|
|
dwAttrib = GetFileAttributesA(m_szTmp);
|
|
if( dwAttrib == (DWORD)0xFFFFFFFF )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Error;
|
|
}
|
|
if( (dwAttrib & FILE_ATTRIBUTE_DIRECTORY) == 0 )
|
|
{
|
|
// This storage is not a directory/folder
|
|
hr = E_FAIL; // @@@@ Is any other value more suitable?
|
|
goto Error;
|
|
}
|
|
|
|
// Get name of file asked for
|
|
|
|
DWORD dwLen = wcslen(m_wcsName);
|
|
|
|
if (dwLen == 0)
|
|
{
|
|
hr = E_FAIL;
|
|
goto Error;
|
|
}
|
|
if (dwLen >= ARRAYSIZE(pwszFileName))
|
|
{
|
|
hr = STRSAFE_E_INSUFFICIENT_BUFFER; // defined in strsafe.h
|
|
goto Error;
|
|
}
|
|
|
|
// Get name of file asked for
|
|
wcscpy( pwszFileName, m_wcsName );
|
|
if( pwszFileName[dwLen-1] != L'\\' )
|
|
{
|
|
if (dwLen >= ARRAYSIZE(pwszFileName) - 1)
|
|
{
|
|
hr = STRSAFE_E_INSUFFICIENT_BUFFER; // defined in strsafe.h
|
|
goto Error;
|
|
}
|
|
wcscat( pwszFileName, L"\\" );
|
|
}
|
|
|
|
hrTemp = StringCchCatW( pwszFileName,
|
|
ARRAYSIZE(pwszFileName),
|
|
pszStorageName );
|
|
|
|
if (FAILED(hrTemp))
|
|
{
|
|
// The file does not exist
|
|
hr = E_FAIL; // @@@@ Change this?
|
|
goto Error;
|
|
}
|
|
|
|
// Check if the file exists
|
|
CWRg(WideCharToMultiByte(CP_ACP, NULL, pwszFileName, -1, m_szTmp, MAX_PATH, NULL, NULL));
|
|
if( GetFileAttributesA( m_szTmp ) == -1 )
|
|
{
|
|
// The file does not exist
|
|
hr = S_FALSE; // @@@@ Should this be a failure code?
|
|
goto Error;
|
|
}
|
|
|
|
// Create new storage object
|
|
hr = CComObject<CMDSPStorage>::CreateInstance(&pStg);
|
|
hr = pStg->QueryInterface( IID_IMDSPStorage, reinterpret_cast<void**>(ppStorage));
|
|
// wcscpy(pStg->m_wcsName, pwszFileName);
|
|
hrTemp = StringCchCopyW(pStg->m_wcsName, ARRAYSIZE(pStg->m_wcsName), pwszFileName);
|
|
if (FAILED(hrTemp))
|
|
{
|
|
hr = hrTemp;
|
|
(*ppStorage)->Release();
|
|
pStg = NULL; // to prevent its deletion below
|
|
goto Error;
|
|
}
|
|
|
|
Error:
|
|
if( hr != S_OK )
|
|
{
|
|
if( pStg ) delete pStg;
|
|
*ppStorage = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::CreateStorage2(
|
|
DWORD dwAttributes,
|
|
DWORD dwAttributesEx,
|
|
_WAVEFORMATEX *pAudioFormat,
|
|
_VIDEOINFOHEADER *pVideoFormat,
|
|
LPWSTR pwszName,
|
|
ULONGLONG qwFileSize,
|
|
IMDSPStorage **ppNewStorage )
|
|
{
|
|
// pVideoFormat, dwAttributesEx not used right now
|
|
return CreateStorage( dwAttributes, pAudioFormat, pwszName, ppNewStorage );
|
|
}
|
|
|
|
|
|
STDMETHODIMP CMDSPStorage::SetAttributes2(
|
|
DWORD dwAttributes,
|
|
DWORD dwAttributesEx,
|
|
_WAVEFORMATEX *pAudioFormat,
|
|
_VIDEOINFOHEADER* pVideoFormat )
|
|
{
|
|
// pVideoFormat, dwAttributesEx not used right now
|
|
return SetAttributes( dwAttributes, pAudioFormat );
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::GetAttributes2(
|
|
DWORD *pdwAttributes,
|
|
DWORD *pdwAttributesEx,
|
|
_WAVEFORMATEX *pAudioFormat,
|
|
_VIDEOINFOHEADER* pVideoFormat )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CARg( pdwAttributesEx );
|
|
*pdwAttributesEx = 0;
|
|
|
|
// pVideoFormat, dwAttributesEx not used right now
|
|
hr = GetAttributes( pdwAttributes, pAudioFormat );
|
|
|
|
Error:
|
|
return hr;
|
|
}
|
|
|
|
|
|
// IMDSPObjectInfo
|
|
STDMETHODIMP CMDSPStorage::GetPlayLength(/*[out]*/ DWORD *pdwLength)
|
|
{
|
|
HRESULT hr;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
if ( !pdwLength )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
hr = WMDM_E_NOTSUPPORTED;
|
|
}
|
|
|
|
Error:
|
|
|
|
hrLogDWORD("IMDSPObjectInfo::GetPlayLength returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::SetPlayLength(/*[in]*/ DWORD dwLength)
|
|
{
|
|
HRESULT hr = WMDM_E_NOTSUPPORTED;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
Error:
|
|
|
|
hrLogDWORD("IMDSPObjectInfo::SetPlayLength returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::GetPlayOffset(/*[out]*/ DWORD *pdwOffset)
|
|
{
|
|
HRESULT hr;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
if ( !pdwOffset )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
hr = WMDM_E_NOTSUPPORTED;
|
|
}
|
|
|
|
Error:
|
|
|
|
hrLogDWORD("IMDSPObjectInfo::GetPlayOffset returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::SetPlayOffset(/*[in]*/ DWORD dwOffset)
|
|
{
|
|
HRESULT hr = WMDM_E_NOTSUPPORTED;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
Error:
|
|
|
|
hrLogDWORD("IMDSPObjectInfo::SetPlayOffset returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::GetTotalLength(/*[out]*/ DWORD *pdwLength)
|
|
{
|
|
HRESULT hr;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
if ( !pdwLength )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
hr = WMDM_E_NOTSUPPORTED;
|
|
}
|
|
|
|
Error:
|
|
|
|
hrLogDWORD("IMDSPObjectInfo::GetTotalLength returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::GetLastPlayPosition(/*[out]*/ DWORD *pdwLastPos)
|
|
{
|
|
HRESULT hr;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
if ( !pdwLastPos )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
hr = WMDM_E_NOTSUPPORTED;
|
|
}
|
|
|
|
Error:
|
|
|
|
hrLogDWORD("IMDSPObjectInfo::GetLastPlayPosition returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::GetLongestPlayPosition(/*[out]*/ DWORD *pdwLongestPos)
|
|
{
|
|
HRESULT hr;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
if ( !pdwLongestPos )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
hr = WMDM_E_NOTSUPPORTED;
|
|
}
|
|
|
|
Error:
|
|
|
|
hrLogDWORD("IMDSPObjectInfo::GetLongestPlayPosition returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
// IMDSPObject
|
|
STDMETHODIMP CMDSPStorage::Open(/*[in]*/ UINT fuMode)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwMode;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
CONEg(m_wcsName[0]);
|
|
|
|
if( m_hFile != INVALID_HANDLE_VALUE )
|
|
{
|
|
hr = WMDM_E_BUSY;
|
|
goto Error;
|
|
}
|
|
|
|
WideCharToMultiByte(CP_ACP, NULL, m_wcsName, -1, m_szTmp, MAX_PATH, NULL, NULL);
|
|
dwMode = GetFileAttributesA(m_szTmp);
|
|
if( (dwMode & FILE_ATTRIBUTE_DIRECTORY) )
|
|
{
|
|
hr=WMDM_E_NOTSUPPORTED;
|
|
}
|
|
else
|
|
{
|
|
dwMode = 0;
|
|
|
|
if(fuMode & MDSP_WRITE )
|
|
{
|
|
dwMode |= GENERIC_WRITE;
|
|
}
|
|
if(fuMode & MDSP_READ )
|
|
{
|
|
dwMode |= GENERIC_READ;
|
|
}
|
|
|
|
m_hFile = CreateFileA(
|
|
m_szTmp,
|
|
dwMode,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
|
|
hr = ( m_hFile == INVALID_HANDLE_VALUE ) ? E_FAIL : S_OK;
|
|
}
|
|
|
|
Error:
|
|
|
|
hrLogDWORD("IMDSPObject::Open returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::Read(
|
|
BYTE *pData,
|
|
DWORD *pdwSize,
|
|
BYTE abMac[WMDM_MAC_LENGTH])
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwToRead;
|
|
DWORD dwRead = NULL;
|
|
BYTE *pTmpData = NULL;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
CARg(pData);
|
|
CARg(pdwSize);
|
|
|
|
dwToRead = *pdwSize;
|
|
|
|
if( m_hFile == INVALID_HANDLE_VALUE )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
pTmpData = new BYTE [dwToRead] ;
|
|
|
|
CPRg(pTmpData);
|
|
|
|
if( ReadFile(m_hFile,(LPVOID)pTmpData,dwToRead,&dwRead,NULL) )
|
|
{
|
|
*pdwSize = dwRead;
|
|
|
|
if( dwRead )
|
|
{
|
|
// MAC the parameters
|
|
HMAC hMAC;
|
|
|
|
CORg(g_pAppSCServer->MACInit(&hMAC));
|
|
CORg(g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pTmpData), dwRead));
|
|
CORg(g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pdwSize), sizeof(DWORD)));
|
|
CORg(g_pAppSCServer->MACFinal(hMAC, abMac));
|
|
|
|
CORg(g_pAppSCServer->EncryptParam(pTmpData, dwRead));
|
|
|
|
memcpy(pData, pTmpData, dwRead);
|
|
}
|
|
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
*pdwSize = 0;
|
|
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
Error:
|
|
|
|
if(pTmpData)
|
|
{
|
|
delete [] pTmpData;
|
|
}
|
|
|
|
hrLogDWORD("IMDSPObject::Read returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::Write(BYTE *pData, DWORD *pdwSize,
|
|
BYTE abMac[WMDM_MAC_LENGTH])
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwWritten = 0;
|
|
BYTE *pTmpData = NULL;
|
|
BYTE pSelfMac[WMDM_MAC_LENGTH];
|
|
|
|
CARg(pData);
|
|
CARg(pdwSize);
|
|
|
|
if( m_hFile == INVALID_HANDLE_VALUE )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
pTmpData = new BYTE [*pdwSize];
|
|
CPRg(pTmpData);
|
|
memcpy(pTmpData, pData, *pdwSize);
|
|
|
|
// Decrypt the pData Parameter
|
|
CHRg(g_pAppSCServer->DecryptParam(pTmpData, *pdwSize));
|
|
|
|
HMAC hMAC;
|
|
CORg(g_pAppSCServer->MACInit(&hMAC));
|
|
CORg(g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pTmpData), *pdwSize));
|
|
CORg(g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pdwSize), sizeof(*pdwSize)));
|
|
CORg(g_pAppSCServer->MACFinal(hMAC, pSelfMac));
|
|
|
|
if (memcmp(abMac, pSelfMac, WMDM_MAC_LENGTH) != 0)
|
|
{
|
|
hr = WMDM_E_MAC_CHECK_FAILED;
|
|
goto Error;
|
|
}
|
|
|
|
if( WriteFile(m_hFile,pTmpData,*pdwSize,&dwWritten,NULL) )
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
*pdwSize = dwWritten;
|
|
|
|
Error:
|
|
|
|
if( pTmpData )
|
|
{
|
|
delete [] pTmpData;
|
|
}
|
|
|
|
hrLogDWORD("IMDSPObject::Write returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::Delete(UINT fuMode, IWMDMProgress *pProgress)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
BOOL bProgressStarted = FALSE;
|
|
BOOL bBusyStatusSet = FALSE;
|
|
DWORD dwStatus = NULL;
|
|
|
|
if( pProgress )
|
|
{
|
|
CORg(pProgress->Begin(100));
|
|
bProgressStarted=TRUE;
|
|
}
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
CONEg(m_wcsName[0]);
|
|
|
|
if ( m_hFile != INVALID_HANDLE_VALUE )
|
|
{
|
|
CloseHandle(m_hFile);
|
|
m_hFile = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
CHRg(GetGlobalDeviceStatus(m_wcsName, &dwStatus));
|
|
if( dwStatus & WMDM_STATUS_BUSY )
|
|
{
|
|
hr = WMDM_E_BUSY;
|
|
goto Error;
|
|
}
|
|
|
|
dwStatus |= (WMDM_STATUS_BUSY | WMDM_STATUS_STORAGECONTROL_DELETING );
|
|
CHRg(SetGlobalDeviceStatus(m_wcsName, dwStatus, TRUE));
|
|
bBusyStatusSet=TRUE;
|
|
|
|
WideCharToMultiByte(CP_ACP, NULL, m_wcsName, -1, m_szTmp, MAX_PATH, NULL, NULL);
|
|
if( fuMode & WMDM_MODE_RECURSIVE )
|
|
{
|
|
CORg(DeleteFileRecursive(m_szTmp));
|
|
}
|
|
else
|
|
{
|
|
if( FILE_ATTRIBUTE_DIRECTORY & GetFileAttributesA(m_szTmp) )
|
|
{
|
|
CWRg(RemoveDirectory(m_szTmp));
|
|
}
|
|
else
|
|
{
|
|
CWRg(DeleteFileA(m_szTmp));
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
Error:
|
|
|
|
if( bBusyStatusSet )
|
|
{
|
|
dwStatus &= (~(WMDM_STATUS_BUSY | WMDM_STATUS_STORAGECONTROL_DELETING ));
|
|
SetGlobalDeviceStatus(m_wcsName, dwStatus, TRUE);
|
|
}
|
|
|
|
if( hr == S_OK )
|
|
{
|
|
m_wcsName[0] = NULL; // Nullify the storage name
|
|
}
|
|
|
|
if( bProgressStarted )
|
|
{
|
|
pProgress->Progress( 100 );
|
|
pProgress->End();
|
|
}
|
|
|
|
hrLogDWORD("IMDSPObject::Delete returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::Seek(/*[in]*/ UINT fuFlags, /*[in]*/ DWORD dwOffset)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
CONEg(m_wcsName[0]);
|
|
CFRg( m_hFile != INVALID_HANDLE_VALUE );
|
|
|
|
DWORD dwMoveMethod;
|
|
|
|
switch (fuFlags)
|
|
{
|
|
case MDSP_SEEK_BOF:
|
|
dwMoveMethod = FILE_BEGIN;
|
|
break;
|
|
|
|
case MDSP_SEEK_CUR:
|
|
dwMoveMethod = FILE_CURRENT;
|
|
break;
|
|
|
|
case MDSP_SEEK_EOF:
|
|
dwMoveMethod = FILE_END;
|
|
break;
|
|
|
|
default:
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
CWRg( (DWORD)0xFFFFFFFF != SetFilePointer(m_hFile, dwOffset, NULL, dwMoveMethod ) );
|
|
|
|
Error:
|
|
|
|
hrLogDWORD("IMDSPObject::Seek returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::Rename(/*[in]*/ LPWSTR pwszNewName, IWMDMProgress *pProgress)
|
|
{
|
|
HRESULT hr;
|
|
BOOL bProgressStarted = FALSE;
|
|
BOOL bBusyStatusSet = FALSE;
|
|
DWORD dwStatus;
|
|
|
|
if( pProgress )
|
|
{
|
|
CORg(pProgress->Begin(100));
|
|
bProgressStarted=TRUE;
|
|
}
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
CARg(pwszNewName);
|
|
CONEg(m_wcsName[0]);
|
|
CFRg(wcslen(m_wcsName)>3); // cannot rename a root storage
|
|
|
|
|
|
|
|
if ( m_hFile != INVALID_HANDLE_VALUE )
|
|
{
|
|
CloseHandle(m_hFile);
|
|
m_hFile = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
CHRg(GetGlobalDeviceStatus(m_wcsName, &dwStatus));
|
|
|
|
if( dwStatus & WMDM_STATUS_BUSY )
|
|
{
|
|
hr=WMDM_E_BUSY;
|
|
goto Error;
|
|
}
|
|
|
|
dwStatus |= (WMDM_STATUS_BUSY | WMDM_STATUS_STORAGECONTROL_MOVING );
|
|
CHRg(SetGlobalDeviceStatus(m_wcsName, dwStatus, TRUE));
|
|
bBusyStatusSet = TRUE;
|
|
|
|
char *pDirOffset;
|
|
char szUpper[MAX_PATH], szNewFullPath[MAX_PATH], szNew[MAX_PATH];
|
|
CWRg(WideCharToMultiByte(CP_ACP, NULL, m_wcsName, -1, m_szTmp, MAX_PATH, NULL, NULL));
|
|
CWRg(WideCharToMultiByte(CP_ACP, NULL, pwszNewName, -1, szNew, MAX_PATH, NULL, NULL));
|
|
|
|
// From m_szTmp, find the upper level dir, and put it in szUpper.
|
|
strcpy(szUpper, m_szTmp);
|
|
if( szUpper[strlen(szUpper)-1] == 0x5c )
|
|
{
|
|
szUpper[strlen(szUpper)-1] = 0;
|
|
}
|
|
pDirOffset = strrchr(szUpper, 0x5c);
|
|
if( pDirOffset )
|
|
{
|
|
*((char *)pDirOffset+1) = 0;
|
|
}
|
|
|
|
// From szUpper and szNew, form the full path for szNewFullPath
|
|
strcpy(szNewFullPath, szUpper);
|
|
pDirOffset=strrchr(szNew, 0x5c);
|
|
if( pDirOffset )
|
|
{
|
|
// strcat(szNewFullPath, (char*)pDirOffset+1);
|
|
hr = StringCchCatA(szNewFullPath, ARRAYSIZE(szNewFullPath), (char*)pDirOffset+1);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Error;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// strcat(szNewFullPath, szNew);
|
|
hr = StringCchCatA(szNewFullPath, ARRAYSIZE(szNewFullPath), szNew);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Error;
|
|
}
|
|
}
|
|
|
|
// Now move
|
|
CWRg ( MoveFileA(m_szTmp, szNewFullPath) );
|
|
|
|
MultiByteToWideChar(CP_ACP, NULL, szNewFullPath, -1, m_wcsName, MAX_PATH);
|
|
|
|
hr = S_OK;
|
|
|
|
Error:
|
|
if( bBusyStatusSet )
|
|
{
|
|
dwStatus &= (~(WMDM_STATUS_BUSY | WMDM_STATUS_STORAGECONTROL_MOVING ));
|
|
SetGlobalDeviceStatus(m_wcsName, dwStatus, TRUE);
|
|
}
|
|
|
|
if( bProgressStarted )
|
|
{
|
|
pProgress->Progress( 100 );
|
|
pProgress->End();
|
|
}
|
|
|
|
hrLogDWORD("IMDSPObject::Rename returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CMDSPStorage::EnumStorage(IMDSPEnumStorage * * ppEnumStorage)
|
|
{
|
|
HRESULT hr;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
CARg(ppEnumStorage);
|
|
CONEg(m_wcsName[0]);
|
|
|
|
DWORD dwAttrib;
|
|
CORg(GetAttributes(&dwAttrib, NULL));
|
|
if( dwAttrib & WMDM_FILE_ATTR_FILE )
|
|
{
|
|
return WMDM_E_NOTSUPPORTED;
|
|
}
|
|
|
|
CComObject<CMDSPEnumStorage> *pEnumObj;
|
|
CORg(CComObject<CMDSPEnumStorage>::CreateInstance(&pEnumObj));
|
|
hr = pEnumObj->QueryInterface(
|
|
IID_IMDSPEnumStorage,
|
|
reinterpret_cast<void**>(ppEnumStorage)
|
|
);
|
|
if( FAILED(hr) )
|
|
{
|
|
delete pEnumObj;
|
|
}
|
|
else
|
|
{
|
|
// wcscpy(pEnumObj->m_wcsPath, m_wcsName);
|
|
hr = StringCchCopyW(pEnumObj->m_wcsPath,
|
|
ARRAYSIZE(pEnumObj->m_wcsPath), m_wcsName);
|
|
if (FAILED(hr))
|
|
{
|
|
(*ppEnumStorage)->Release();
|
|
*ppEnumStorage = NULL;
|
|
}
|
|
}
|
|
|
|
Error:
|
|
|
|
hrLogDWORD("IMDSPStorage::EnumStorage returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::Close()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
CONEg(m_wcsName[0]);
|
|
if( m_hFile != INVALID_HANDLE_VALUE )
|
|
{
|
|
CloseHandle(m_hFile);
|
|
m_hFile=INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
Error:
|
|
|
|
hrLogDWORD("IMDSPObject::Close returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
DWORD MoveFunc( void *args )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
MOVETHREADARGS *pCMArgs;
|
|
WCHAR *pWcs;
|
|
CHAR szDst[MAX_PATH];
|
|
CHAR szSrc[MAX_PATH];
|
|
|
|
pCMArgs = (MOVETHREADARGS *)args;
|
|
|
|
if( pCMArgs->bNewThread )
|
|
{
|
|
CORg(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED));
|
|
|
|
if( pCMArgs->pProgress )
|
|
{
|
|
CORg(CoGetInterfaceAndReleaseStream(
|
|
pCMArgs->pStream,
|
|
IID_IWMDMProgress,
|
|
(LPVOID *)&(pCMArgs->pProgress))
|
|
);
|
|
}
|
|
}
|
|
|
|
pWcs = wcsrchr(pCMArgs->wcsSrc, 0x5c);
|
|
if(!pWcs)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
|
|
goto Error;
|
|
}
|
|
DWORD dwDestLen = wcslen(pCMArgs->wcsDst);
|
|
if (dwDestLen == 0)
|
|
{
|
|
// Code below assumes this string is at least one long
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
|
|
goto Error;
|
|
}
|
|
|
|
// Validate buffer sizes before the string copies
|
|
int nHave = ARRAYSIZE(pCMArgs->wcsDst) - 1; // -1 for NULL terminator
|
|
nHave -= dwDestLen;
|
|
if( pCMArgs->wcsDst[dwDestLen-1] != 0x5c )
|
|
{
|
|
nHave -= BACKSLASH_STRING_LENGTH;
|
|
}
|
|
nHave -= wcslen(pWcs+1);
|
|
if (nHave < 0)
|
|
{
|
|
hr = STRSAFE_E_INSUFFICIENT_BUFFER; // defined in strsafe.h
|
|
goto Error;
|
|
}
|
|
|
|
// Validate the buffer size of pCMArgs->pThis->m_wcsName before
|
|
// calling UtilMoveFile. ARRAYSIZE(pCMArgs->wcsDst) - nHave is
|
|
// the length of the string (including the NULL terminator)
|
|
// that will be constructed in pCMArgs->wcsDst and copied over to
|
|
// pCMArgs->pThis->m_wcsName
|
|
if (ARRAYSIZE(pCMArgs->wcsDst) - nHave > ARRAYSIZE(pCMArgs->pThis->m_wcsName))
|
|
{
|
|
hr = STRSAFE_E_INSUFFICIENT_BUFFER; // defined in strsafe.h
|
|
goto Error;
|
|
}
|
|
|
|
if( pCMArgs->wcsDst[dwDestLen-1] != 0x5c )
|
|
{
|
|
wcscat(pCMArgs->wcsDst,g_wcsBackslash);
|
|
}
|
|
wcscat(pCMArgs->wcsDst, pWcs+1);
|
|
|
|
WideCharToMultiByte(CP_ACP, NULL, pCMArgs->wcsDst, -1, szDst, MAX_PATH, NULL, NULL);
|
|
WideCharToMultiByte(CP_ACP, NULL, pCMArgs->wcsSrc, -1, szSrc, MAX_PATH, NULL, NULL);
|
|
|
|
CWRg( MoveFileA(szSrc,szDst) );
|
|
|
|
// Substitute current object name with the moved one
|
|
wcscpy(pCMArgs->pThis->m_wcsName, pCMArgs->wcsDst);
|
|
|
|
hr = S_OK;
|
|
|
|
Error:
|
|
|
|
if( pCMArgs->bNewThread )
|
|
{
|
|
// Reset status, we've got here we must have set the status busy before
|
|
pCMArgs->dwStatus &= (~(WMDM_STATUS_BUSY | WMDM_STATUS_STORAGECONTROL_MOVING));
|
|
SetGlobalDeviceStatus(pCMArgs->wcsSrc, pCMArgs->dwStatus, TRUE);
|
|
|
|
// Reset progress, we've got here we must have set the progress before
|
|
if( pCMArgs->pProgress )
|
|
{
|
|
pCMArgs->pProgress->Progress(100);
|
|
pCMArgs->pProgress->End();
|
|
pCMArgs->pProgress->Release(); // since we did AddRef to get here
|
|
}
|
|
|
|
if( pCMArgs )
|
|
{
|
|
delete pCMArgs;
|
|
}
|
|
|
|
CoUninitialize();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMDSPStorage::Move(UINT fuMode, IWMDMProgress *pProgress,
|
|
IMDSPStorage *pTarget)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
WCHAR *wcsSrc = NULL;
|
|
WCHAR *wcsDst = NULL;
|
|
WCHAR wcsTmp[MAX_PATH];
|
|
WCHAR *pWcs = NULL;
|
|
CMDSPStorage *pStg = NULL;
|
|
MOVETHREADARGS *pMoveArgs = NULL;
|
|
DWORD dwThreadID;
|
|
DWORD dwStatus = NULL;
|
|
BOOL bProgStarted = FALSE;
|
|
BOOL bBusyStatusSet = FALSE;
|
|
BOOL bThreadFailed = TRUE;
|
|
BOOL bAddRefed = FALSE;
|
|
|
|
// Start the progress
|
|
if( pProgress )
|
|
{
|
|
CORg(pProgress->Begin(100));
|
|
bProgStarted=TRUE;
|
|
}
|
|
|
|
CFRg(g_pAppSCServer);
|
|
if ( !(g_pAppSCServer->fIsAuthenticated()) )
|
|
{
|
|
CORg(WMDM_E_NOTCERTIFIED);
|
|
}
|
|
|
|
CONEg(m_wcsName[0]);
|
|
|
|
CHRg(GetGlobalDeviceStatus(m_wcsName, &dwStatus));
|
|
|
|
if( dwStatus & WMDM_STATUS_BUSY )
|
|
{
|
|
hr = WMDM_E_BUSY;
|
|
goto Error;
|
|
}
|
|
|
|
pMoveArgs = new MOVETHREADARGS;
|
|
CPRg(pMoveArgs);
|
|
ZeroMemory(pMoveArgs, sizeof(MOVETHREADARGS));
|
|
|
|
dwStatus |= (WMDM_STATUS_BUSY | WMDM_STATUS_STORAGECONTROL_MOVING );
|
|
CHRg(SetGlobalDeviceStatus(m_wcsName, dwStatus, TRUE));
|
|
bBusyStatusSet = TRUE;
|
|
|
|
// setup MoveArgs for MoveFunc
|
|
pMoveArgs->dwStatus = dwStatus;
|
|
CARg(pTarget);
|
|
pStg = (CMDSPStorage *)pTarget;
|
|
wcsSrc = (WCHAR *)&(pMoveArgs->wcsSrc[0]);
|
|
CPRg(wcsSrc);
|
|
wcsDst = (WCHAR *)&(pMoveArgs->wcsDst[0]);
|
|
CPRg(wcsDst);
|
|
|
|
// Make sure the source and destination are on the same device
|
|
hr = wcsParseDeviceName(m_wcsName, wcsSrc, ARRAYSIZE(pMoveArgs->wcsSrc));
|
|
if (FAILED(hr))
|
|
{
|
|
goto Error;
|
|
}
|
|
hr = wcsParseDeviceName(pStg->m_wcsName, wcsDst, ARRAYSIZE(pMoveArgs->wcsDst));
|
|
if (FAILED(hr))
|
|
{
|
|
goto Error;
|
|
}
|
|
if( wcscmp(wcsSrc, wcsDst) )
|
|
{
|
|
hr = WMDM_E_NOTSUPPORTED; // do not support move out of the same device
|
|
goto Error;
|
|
}
|
|
|
|
// Now check for target's attributes
|
|
DWORD dwDstAttrib, dwSrcAttrib;
|
|
CHRg(GetAttributes(&dwSrcAttrib, NULL));
|
|
|
|
// wcscpy(wcsSrc, m_wcsName);
|
|
hr = StringCchCopyW(wcsSrc, ARRAYSIZE(pMoveArgs->wcsSrc), m_wcsName);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Error;
|
|
}
|
|
|
|
// wcscpy(wcsDst, pStg->m_wcsName);
|
|
hr = StringCchCopyW(wcsDst, ARRAYSIZE(pMoveArgs->wcsDst), pStg->m_wcsName);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Error;
|
|
}
|
|
|
|
if ( fuMode & WMDM_STORAGECONTROL_INSERTINTO )
|
|
{
|
|
CHRg(pTarget->GetAttributes(&dwDstAttrib, NULL));
|
|
CARg( dwDstAttrib & WMDM_FILE_ATTR_FOLDER ); // INSERTINFO must be to a folder
|
|
}
|
|
else
|
|
{
|
|
// Get the folder one level up
|
|
pWcs = wcsrchr(wcsDst, 0x5c);
|
|
CFRg(pWcs);
|
|
*pWcs=NULL;
|
|
|
|
WideCharToMultiByte(CP_ACP, NULL, m_wcsName, -1, m_szTmp, MAX_PATH, NULL, NULL);
|
|
DWORD dwAttribs = GetFileAttributesA(m_szTmp);
|
|
if (dwAttribs == INVALID_FILE_ATTRIBUTES)
|
|
{
|
|
goto Error;
|
|
}
|
|
CWRg( FILE_ATTRIBUTE_DIRECTORY & dwAttribs );
|
|
}
|
|
|
|
wcscpy(wcsTmp, wcsDst); // Store the destination folder
|
|
|
|
pMoveArgs->pThis = this;
|
|
pMoveArgs->bNewThread =(fuMode & WMDM_MODE_THREAD)?TRUE:FALSE;
|
|
|
|
// Now handle Progress marshaling
|
|
if( pProgress )
|
|
{
|
|
pMoveArgs->pProgress = pProgress;
|
|
pProgress->AddRef(); // since we are going to use it in MoveFunc()
|
|
bAddRefed=TRUE;
|
|
|
|
if( pMoveArgs->bNewThread )
|
|
{
|
|
CORg(CoMarshalInterThreadInterfaceInStream(
|
|
IID_IWMDMProgress,
|
|
(LPUNKNOWN)pProgress,
|
|
(LPSTREAM *)&(pMoveArgs->pStream))
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( m_hFile != INVALID_HANDLE_VALUE )
|
|
{
|
|
CloseHandle(m_hFile);
|
|
m_hFile = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
if( fuMode & WMDM_MODE_BLOCK )
|
|
{
|
|
hr = MoveFunc((void *)pMoveArgs);
|
|
}
|
|
else if ( fuMode & WMDM_MODE_THREAD )
|
|
{
|
|
if( CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MoveFunc,
|
|
(void *)pMoveArgs, 0, &dwThreadID))
|
|
{
|
|
bThreadFailed=FALSE;
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
Error:
|
|
|
|
if( (fuMode&WMDM_MODE_BLOCK) || bThreadFailed ) // otherwise these will be in MoveFunc()
|
|
{
|
|
if( bBusyStatusSet )
|
|
{
|
|
dwStatus &= (~(WMDM_STATUS_BUSY | WMDM_STATUS_STORAGECONTROL_MOVING));
|
|
SetGlobalDeviceStatus(m_wcsName, dwStatus, TRUE);
|
|
}
|
|
if( bProgStarted )
|
|
{
|
|
pProgress->Progress(100);
|
|
pProgress->End();
|
|
}
|
|
if( bAddRefed )
|
|
{
|
|
pProgress->Release(); // since we called AddRef before calling MoveFunc()
|
|
}
|
|
if( pMoveArgs )
|
|
{
|
|
delete pMoveArgs;
|
|
}
|
|
}
|
|
|
|
hrLogDWORD("IMDSPObject::Move returned 0x%08lx", hr, hr);
|
|
|
|
return hr;
|
|
}
|