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.
904 lines
20 KiB
904 lines
20 KiB
//
|
|
// Microsoft Windows Media Technologies
|
|
// © 1999 Microsoft Corporation. All rights reserved.
|
|
//
|
|
// Refer to your End User License Agreement for details on your rights/restrictions to use these sample files.
|
|
//
|
|
|
|
// 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.
|
|
|
|
//***************************************************************************
|
|
//
|
|
// Name: MDSPutil.cpp
|
|
//
|
|
// Description: Utility functions for MDSP
|
|
//
|
|
//***************************************************************************
|
|
|
|
#include "hdspPCH.h"
|
|
#include <SerialNumber.h>
|
|
|
|
#define MDSP_PMID_IOMEGA 2 // from "serialid.h"
|
|
|
|
extern BOOL IsAdministrator(DWORD& dwLastError);
|
|
|
|
UINT __stdcall UtilGetLyraDriveType(LPSTR szDL)
|
|
{
|
|
UINT uType = GetDriveType( szDL );
|
|
|
|
if( DRIVE_REMOVABLE == uType )
|
|
{
|
|
WMDMID stID;
|
|
HRESULT hr;
|
|
WCHAR wcsTmp[4]=L"A:\\";
|
|
|
|
wcsTmp[0] = (USHORT)szDL[0];
|
|
|
|
#define WITH_IOMEGA
|
|
#ifdef WITH_IOMEGA
|
|
extern BOOL __stdcall IsIomegaDrive(DWORD dwDriveNum);
|
|
|
|
DWORD dwLastError;
|
|
if( IsAdministrator(dwLastError) )
|
|
{
|
|
DWORD dwDriveNum;
|
|
if (wcsTmp[0] >= L'A' && wcsTmp[0] <= L'Z')
|
|
{
|
|
dwDriveNum = wcsTmp[0] - L'A';
|
|
}
|
|
else if (wcsTmp[0] >= L'a' && wcsTmp[0] <= L'z')
|
|
{
|
|
dwDriveNum = wcsTmp[0] - L'a';
|
|
}
|
|
else
|
|
{
|
|
// GetDriveType returned DRIVE_REMOVABLE
|
|
// Assuming szDl is nothing more than
|
|
// drive_letter:\, we won't get here.
|
|
|
|
// Following will force IsIomegaDrive to
|
|
// return 0
|
|
dwDriveNum = 26;
|
|
}
|
|
if( !IsIomegaDrive(dwDriveNum) )
|
|
{
|
|
uType = DRIVE_LYRA_TYPE;
|
|
}
|
|
}
|
|
else // ignore dwLastError. If not Administrator, call UtilGetSerialNumber which calls into PMSP Service
|
|
{
|
|
hr = UtilGetSerialNumber(wcsTmp, &stID, 0);
|
|
if( S_OK!=hr || stID.dwVendorID != MDSP_PMID_IOMEGA )
|
|
{
|
|
uType = DRIVE_LYRA_TYPE;
|
|
}
|
|
}
|
|
#else
|
|
hr = UtilGetSerialNumber(wcsTmp, &stID, 0);
|
|
|
|
if( ((S_OK==hr)&&(20==stID.SerialNumberLength)) ||
|
|
(HRESULT_FROM_WIN32(ERROR_INVALID_DATA) == hr)
|
|
)
|
|
{
|
|
uType = DRIVE_LYRA_TYPE;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
else
|
|
{
|
|
uType = DRIVE_UNKNOWN;
|
|
}
|
|
|
|
return uType;
|
|
}
|
|
|
|
BOOL UtilSetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
|
|
{
|
|
if( g_bIsWinNT )
|
|
{
|
|
return SetFileAttributesW(lpFileName, dwFileAttributes);
|
|
}
|
|
else
|
|
{
|
|
BOOL bRet;
|
|
char *szTmp=NULL;
|
|
UINT uLen = 2*(wcslen(lpFileName)+1);
|
|
szTmp = new char [uLen];
|
|
|
|
if(!szTmp)
|
|
{
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
WideCharToMultiByte(CP_ACP, NULL, lpFileName, -1, szTmp, uLen, NULL, NULL);
|
|
|
|
bRet = SetFileAttributesA(szTmp, dwFileAttributes);
|
|
|
|
if( szTmp )
|
|
{
|
|
delete [] szTmp;
|
|
}
|
|
return bRet;
|
|
}
|
|
}
|
|
|
|
BOOL UtilCreateDirectoryW(LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
|
|
{
|
|
if( g_bIsWinNT )
|
|
{
|
|
return CreateDirectoryW(lpPathName, lpSecurityAttributes);
|
|
}
|
|
else
|
|
{
|
|
BOOL bRet;
|
|
char *szTmp=NULL;
|
|
UINT uLen = 2*(wcslen(lpPathName)+1);
|
|
szTmp = new char [uLen];
|
|
|
|
if(!szTmp)
|
|
{
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
WideCharToMultiByte(CP_ACP, NULL, lpPathName, -1, szTmp, uLen, NULL, NULL);
|
|
|
|
bRet = CreateDirectoryA(szTmp, lpSecurityAttributes);
|
|
|
|
if( szTmp )
|
|
{
|
|
delete [] szTmp;
|
|
}
|
|
return bRet;
|
|
}
|
|
}
|
|
|
|
DWORD UtilGetFileAttributesW(LPCWSTR lpFileName)
|
|
{
|
|
if( g_bIsWinNT )
|
|
{
|
|
return GetFileAttributesW(lpFileName);
|
|
}
|
|
else
|
|
{
|
|
DWORD dwRet;
|
|
char *szTmp=NULL;
|
|
UINT uLen = 2*(wcslen(lpFileName)+1);
|
|
szTmp = new char [uLen];
|
|
|
|
if(!szTmp)
|
|
{
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
return 0xFFFFFFFF;
|
|
}
|
|
|
|
WideCharToMultiByte(CP_ACP, NULL, lpFileName, -1, szTmp, uLen, NULL, NULL);
|
|
|
|
dwRet = GetFileAttributesA(szTmp);
|
|
|
|
if( szTmp )
|
|
{
|
|
delete [] szTmp;
|
|
}
|
|
return dwRet;
|
|
}
|
|
}
|
|
|
|
HANDLE UtilCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
|
|
{
|
|
if( g_bIsWinNT )
|
|
{
|
|
return CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
|
}
|
|
else
|
|
{
|
|
HANDLE hRet=INVALID_HANDLE_VALUE;
|
|
char *szTmp=NULL;
|
|
UINT uLen = 2*(wcslen(lpFileName)+1);
|
|
szTmp = new char [uLen];
|
|
|
|
if(!szTmp)
|
|
{
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
return INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
WideCharToMultiByte(CP_ACP, NULL, lpFileName, -1, szTmp, uLen, NULL, NULL);
|
|
|
|
hRet = CreateFileA(szTmp, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
|
|
|
if( szTmp )
|
|
{
|
|
delete [] szTmp;
|
|
}
|
|
return hRet;
|
|
}
|
|
}
|
|
|
|
BOOL UtilMoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
|
|
{
|
|
if( g_bIsWinNT )
|
|
{
|
|
return MoveFileW(lpExistingFileName, lpNewFileName);
|
|
}
|
|
else
|
|
{
|
|
BOOL bRet;
|
|
char *szTmpSrc=NULL, *szTmpDst=NULL;
|
|
szTmpSrc = new char [2*(wcslen(lpExistingFileName)+1)];
|
|
szTmpDst = new char [2*(wcslen(lpNewFileName)+1)];
|
|
|
|
if( (!szTmpSrc) || (!szTmpDst))
|
|
{
|
|
if( szTmpSrc )
|
|
{
|
|
delete [] szTmpSrc;
|
|
szTmpSrc=NULL;
|
|
}
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
WideCharToMultiByte(CP_ACP, NULL, lpExistingFileName, -1, szTmpSrc, 2*(wcslen(lpExistingFileName)+1), NULL, NULL);
|
|
WideCharToMultiByte(CP_ACP, NULL, lpNewFileName, -1, szTmpDst, 2*(wcslen(lpNewFileName)+1), NULL, NULL);
|
|
|
|
bRet = MoveFileA(szTmpSrc, szTmpDst);
|
|
|
|
if( szTmpSrc )
|
|
{
|
|
delete [] szTmpSrc;
|
|
szTmpSrc=NULL;
|
|
}
|
|
if( szTmpDst )
|
|
{
|
|
delete [] szTmpDst;
|
|
szTmpDst=NULL;
|
|
}
|
|
return bRet;
|
|
}
|
|
}
|
|
|
|
void wcsParseDeviceName(WCHAR *wcsIn, WCHAR **wcsOut)
|
|
{
|
|
WCHAR wcsTmp[MAX_PATH], *pWcs;
|
|
|
|
// @@@@ Change to a safe copy, but should we return error codes?
|
|
// wcsIn is MAX_PATH chars for many calls to this function
|
|
wcscpy( wcsTmp, wcsIn );
|
|
|
|
pWcs = wcschr( wcsTmp, 0x5c );
|
|
|
|
if( pWcs )
|
|
{
|
|
*pWcs=0;
|
|
}
|
|
|
|
// @@@@ wcsOut is 32 char in calls from this file
|
|
wcscpy( *wcsOut, wcsTmp );
|
|
}
|
|
|
|
HRESULT GetFileSizeRecursive(char *szPath, DWORD *pdwSizeLow, DWORD *pdwSizeHigh)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
HANDLE hFindFile = INVALID_HANDLE_VALUE;
|
|
DWORD dwSizeLow = 0;
|
|
DWORD dwSizeHigh = 0;
|
|
WIN32_FIND_DATAA fd;
|
|
char szLP[MAX_PATH];
|
|
|
|
CARg( szPath );
|
|
CARg( pdwSizeLow );
|
|
CARg( pdwSizeHigh );
|
|
|
|
strcpy( szLP, szPath );
|
|
if( FILE_ATTRIBUTE_DIRECTORY & GetFileAttributesA(szPath) )
|
|
{
|
|
if( szLP[strlen(szLP)-1] != 0x5c )
|
|
{
|
|
strcat(szLP, g_szBackslash);
|
|
}
|
|
strcat(szLP, "*");
|
|
|
|
hFindFile = FindFirstFileA(szLP, &fd);
|
|
if( hFindFile != INVALID_HANDLE_VALUE )
|
|
{
|
|
if( strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )
|
|
{
|
|
szLP[strlen(szLP)-1] = 0; // erase the '*'
|
|
strcat(szLP, fd.cFileName);
|
|
CORg(GetFileSizeRecursive(szLP, pdwSizeLow, pdwSizeHigh));
|
|
}
|
|
|
|
while ( FindNextFileA(hFindFile, &fd) )
|
|
{
|
|
if( strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )
|
|
{
|
|
strcpy(szLP, szPath);
|
|
if( szLP[strlen(szLP)-1] != 0x5c )
|
|
{
|
|
strcat(szLP, g_szBackslash);
|
|
}
|
|
strcat(szLP, fd.cFileName);
|
|
CORg(GetFileSizeRecursive(szLP, pdwSizeLow, pdwSizeHigh));
|
|
}
|
|
}
|
|
hr = GetLastError();
|
|
if( hr == ERROR_NO_MORE_FILES )
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hFile = CreateFileA(
|
|
szPath,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL
|
|
);
|
|
CWRg(hFile != INVALID_HANDLE_VALUE);
|
|
|
|
dwSizeLow = GetFileSize(hFile, &dwSizeHigh);
|
|
|
|
CloseHandle(hFile);
|
|
|
|
CWRg( 0xFFFFFFFF != dwSizeLow );
|
|
|
|
*pdwSizeLow += dwSizeLow;
|
|
*pdwSizeHigh += dwSizeHigh;
|
|
|
|
hr = S_OK;
|
|
}
|
|
|
|
Error:
|
|
|
|
if( hFindFile != INVALID_HANDLE_VALUE )
|
|
{
|
|
FindClose(hFindFile);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT DeleteFileRecursive(char *szPath)
|
|
{
|
|
HRESULT hr=S_OK;
|
|
|
|
CARg(szPath);
|
|
|
|
if( FILE_ATTRIBUTE_DIRECTORY & GetFileAttributesA(szPath) )
|
|
{
|
|
HANDLE hFindFile = INVALID_HANDLE_VALUE;
|
|
WIN32_FIND_DATAA fd;
|
|
char szLP[MAX_PATH];
|
|
|
|
strcpy(szLP, szPath);
|
|
if( szLP[strlen(szLP)-1] != 0x5c )
|
|
{
|
|
strcat(szLP, g_szBackslash);
|
|
}
|
|
strcat(szLP, "*");
|
|
|
|
hFindFile = FindFirstFileA(szLP, &fd);
|
|
if ( hFindFile != INVALID_HANDLE_VALUE )
|
|
{
|
|
do {
|
|
if( strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )
|
|
{
|
|
strcpy(szLP, szPath);
|
|
if( szLP[strlen(szLP)-1] != 0x5c )
|
|
{
|
|
strcat(szLP, g_szBackslash);
|
|
}
|
|
strcat(szLP, fd.cFileName);
|
|
CHRg(DeleteFileRecursive(szLP));
|
|
}
|
|
} while ( FindNextFileA(hFindFile, &fd) ) ;
|
|
|
|
FindClose(hFindFile);
|
|
|
|
hr = GetLastError();
|
|
}
|
|
else
|
|
{
|
|
hr = GetLastError();
|
|
}
|
|
|
|
// Until here this dir should be empty
|
|
if( hr == ERROR_NO_MORE_FILES )
|
|
{
|
|
CWRg(RemoveDirectory(szPath));
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CWRg( DeleteFileA(szPath) );
|
|
}
|
|
|
|
Error:
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT SetGlobalDeviceStatus(WCHAR *wcsNameIn, DWORD dwStat, BOOL bClear)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
WCHAR wcsName[32];
|
|
WCHAR *pWN;
|
|
int i;
|
|
|
|
g_CriticalSection.Lock();
|
|
|
|
CARg(wcsNameIn);
|
|
|
|
pWN = &wcsName[0];
|
|
wcsParseDeviceName(wcsNameIn, &pWN);
|
|
|
|
// Search for existing entries to see if there is a match
|
|
//
|
|
for( i=0; i<MDSP_MAX_DEVICE_OBJ; i++ )
|
|
{
|
|
if( g_GlobalDeviceInfo[i].bValid )
|
|
{
|
|
if(!wcscmp(wcsName, g_GlobalDeviceInfo[i].wcsDevName) )
|
|
{
|
|
if( bClear )
|
|
{
|
|
g_GlobalDeviceInfo[i].dwStatus = dwStat;
|
|
}
|
|
else
|
|
{
|
|
g_GlobalDeviceInfo[i].dwStatus |= dwStat;
|
|
}
|
|
|
|
break; // a match has been found;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !(i<MDSP_MAX_DEVICE_OBJ) ) // new entry
|
|
{
|
|
for(i=0; i<MDSP_MAX_DEVICE_OBJ; i++)
|
|
{
|
|
if( !(g_GlobalDeviceInfo[i].bValid) ) // found empty space
|
|
{
|
|
wcscpy(g_GlobalDeviceInfo[i].wcsDevName, wcsName);
|
|
g_GlobalDeviceInfo[i].bValid = TRUE;
|
|
g_GlobalDeviceInfo[i].dwStatus = dwStat;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( i<MDSP_MAX_DEVICE_OBJ )
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = hrNoMem;
|
|
}
|
|
|
|
Error:
|
|
|
|
g_CriticalSection.Unlock();
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT GetGlobalDeviceStatus(WCHAR *wcsNameIn, DWORD *pdwStat)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
WCHAR wcsName[32];
|
|
WCHAR *pWN;
|
|
int i;
|
|
|
|
CARg(wcsNameIn);
|
|
|
|
pWN = &wcsName[0];
|
|
wcsParseDeviceName(wcsNameIn, &pWN);
|
|
|
|
// Search for existing entries to see if there is a match
|
|
//
|
|
for( i=0; i<MDSP_MAX_DEVICE_OBJ; i++ )
|
|
{
|
|
if( g_GlobalDeviceInfo[i].bValid )
|
|
{
|
|
if(!wcscmp(wcsName, g_GlobalDeviceInfo[i].wcsDevName) )
|
|
{
|
|
*pdwStat = g_GlobalDeviceInfo[i].dwStatus;
|
|
break; // a match has been found;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( i<MDSP_MAX_DEVICE_OBJ )
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
Error:
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT QuerySubFoldersAndFilesW(LPCWSTR wcsCurrentFolder, DWORD *pdwAttr)
|
|
{
|
|
HRESULT hr=E_FAIL;
|
|
LPWSTR wcsName=NULL;
|
|
int len;
|
|
WIN32_FIND_DATAW wfd;
|
|
int nErrorEnd=0;
|
|
HANDLE hFFile=INVALID_HANDLE_VALUE;
|
|
DWORD dwAttrib;
|
|
|
|
CARg(wcsCurrentFolder);
|
|
CARg(pdwAttr);
|
|
|
|
len=wcslen(wcsCurrentFolder);
|
|
CARg(len>2);
|
|
|
|
wcsName = new WCHAR [len+MAX_PATH];
|
|
CPRg(wcsName);
|
|
|
|
wcscpy(wcsName, wcsCurrentFolder);
|
|
if( wcsName[wcslen(wcsName)-1] != 0x5c )
|
|
{
|
|
wcscat(wcsName, g_wcsBackslash);
|
|
}
|
|
wcscat(wcsName, L"*");
|
|
|
|
|
|
while( !nErrorEnd )
|
|
{
|
|
if( hFFile == INVALID_HANDLE_VALUE )
|
|
{
|
|
hFFile = FindFirstFileW(wcsName, &wfd);
|
|
if( hFFile == INVALID_HANDLE_VALUE )
|
|
{
|
|
nErrorEnd = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( !FindNextFileW(hFFile, &wfd) )
|
|
{
|
|
nErrorEnd = 1;
|
|
}
|
|
}
|
|
|
|
if ( !nErrorEnd && hFFile != INVALID_HANDLE_VALUE )
|
|
{
|
|
if( !wcscmp(wfd.cFileName, L".") || !wcscmp(wfd.cFileName, L"..") )
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
wcscpy(wcsName, wcsCurrentFolder);
|
|
if( wcsName[wcslen(wcsName)-1] != 0x5c )
|
|
{
|
|
wcscat(wcsName, g_wcsBackslash);
|
|
}
|
|
wcscat(wcsName, wfd.cFileName);
|
|
dwAttrib = GetFileAttributesW(wcsName);
|
|
if( dwAttrib & FILE_ATTRIBUTE_DIRECTORY )
|
|
{
|
|
*pdwAttr |= WMDM_STORAGE_ATTR_HAS_FOLDERS;
|
|
// definition is in MDSPdefs.h #define ALSO_CHECK_FILES
|
|
#ifndef ALSO_CHECK_FILES
|
|
break;
|
|
#endif
|
|
}
|
|
#ifdef ALSO_CHECK_FILES
|
|
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
|
|
}
|
|
#endif
|
|
}
|
|
} // End of If
|
|
} // End of while
|
|
|
|
hr=S_OK;
|
|
Error:
|
|
if( hFFile != INVALID_HANDLE_VALUE )
|
|
{
|
|
FindClose(hFFile);
|
|
}
|
|
if( wcsName )
|
|
{
|
|
delete [] wcsName;
|
|
}
|
|
return hr; // If FAILED(hr), sorry, can't do it.
|
|
}
|
|
|
|
HRESULT QuerySubFoldersAndFilesA(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+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;
|
|
// definition is in MDSPdefs.h #define ALSO_CHECK_FILES
|
|
#ifndef ALSO_CHECK_FILES
|
|
break;
|
|
#endif
|
|
}
|
|
#ifdef ALSO_CHECK_FILES
|
|
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
|
|
}
|
|
#endif
|
|
}
|
|
} // 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.
|
|
}
|
|
|
|
|
|
HRESULT QuerySubFoldersAndFiles(LPCWSTR wcsCurrentFolder, DWORD *pdwAttr)
|
|
{
|
|
if( g_bIsWinNT )
|
|
{
|
|
return QuerySubFoldersAndFilesW(wcsCurrentFolder, pdwAttr);
|
|
}
|
|
else
|
|
{
|
|
HRESULT hr;
|
|
char *szTmp=NULL;
|
|
UINT uLen = 2*(wcslen(wcsCurrentFolder)+1);
|
|
|
|
szTmp = new char [uLen];
|
|
if(!szTmp)
|
|
{
|
|
return HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
|
|
}
|
|
|
|
WideCharToMultiByte(CP_ACP, NULL, wcsCurrentFolder, -1, szTmp, uLen, NULL, NULL);
|
|
hr = QuerySubFoldersAndFilesA(szTmp, pdwAttr);
|
|
if( szTmp )
|
|
{
|
|
delete [] szTmp;
|
|
}
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
HRESULT DeleteFileRecursiveW(WCHAR *wcsPath)
|
|
{
|
|
HRESULT hr=S_OK;
|
|
|
|
CARg(wcsPath);
|
|
|
|
if( FILE_ATTRIBUTE_DIRECTORY & GetFileAttributesW(wcsPath) )
|
|
{
|
|
HANDLE hFindFile=INVALID_HANDLE_VALUE;
|
|
WIN32_FIND_DATAW wfd;
|
|
WCHAR wcsLP[MAX_PATH];
|
|
|
|
wcscpy(wcsLP, wcsPath);
|
|
if( wcsLP[wcslen(wcsLP)-1] != 0x5c )
|
|
{
|
|
wcscat(wcsLP, g_wcsBackslash);
|
|
}
|
|
wcscat(wcsLP, L"*");
|
|
hFindFile = FindFirstFileW(wcsLP, &wfd);
|
|
if ( hFindFile != INVALID_HANDLE_VALUE )
|
|
{
|
|
do {
|
|
if( wcscmp(wfd.cFileName, L".") && wcscmp(wfd.cFileName, L"..") )
|
|
{
|
|
wcscpy(wcsLP, wcsPath);
|
|
if( wcsLP[wcslen(wcsLP)-1] != 0x5c )
|
|
{
|
|
wcscat(wcsLP, g_wcsBackslash);
|
|
}
|
|
wcscat(wcsLP, wfd.cFileName);
|
|
CHRg(DeleteFileRecursiveW(wcsLP));
|
|
}
|
|
} while ( FindNextFileW(hFindFile, &wfd) ) ;
|
|
|
|
FindClose(hFindFile);
|
|
hr = GetLastError();
|
|
} else {
|
|
hr = GetLastError();
|
|
}
|
|
|
|
// Until here this dir should be empty
|
|
if( hr == ERROR_NO_MORE_FILES )
|
|
{
|
|
CWRg(RemoveDirectoryW(wcsPath));
|
|
hr=S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CWRg( DeleteFileW(wcsPath) );
|
|
}
|
|
|
|
Error:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT DeleteFileRecursiveA(char *szPath)
|
|
{
|
|
HRESULT hr=S_OK;
|
|
|
|
CARg(szPath);
|
|
|
|
if( FILE_ATTRIBUTE_DIRECTORY & GetFileAttributesA(szPath) )
|
|
{
|
|
HANDLE hFindFile=INVALID_HANDLE_VALUE;
|
|
WIN32_FIND_DATAA fd;
|
|
char szLP[MAX_PATH];
|
|
|
|
strcpy(szLP, szPath);
|
|
if( szLP[strlen(szLP)-1] != 0x5c )
|
|
{
|
|
strcat(szLP, g_szBackslash);
|
|
}
|
|
strcat(szLP, "*");
|
|
hFindFile = FindFirstFileA(szLP, &fd);
|
|
if ( hFindFile != INVALID_HANDLE_VALUE )
|
|
{
|
|
do {
|
|
if( strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )
|
|
{
|
|
strcpy(szLP, szPath);
|
|
if( szLP[strlen(szLP)-1] != 0x5c )
|
|
{
|
|
strcat(szLP, g_szBackslash);
|
|
}
|
|
strcat(szLP, fd.cFileName);
|
|
CHRg(DeleteFileRecursiveA(szLP));
|
|
}
|
|
} while ( FindNextFileA(hFindFile, &fd) ) ;
|
|
|
|
FindClose(hFindFile);
|
|
hr = GetLastError();
|
|
}
|
|
else
|
|
{
|
|
hr = GetLastError();
|
|
}
|
|
|
|
// Until here this dir should be empty
|
|
if( hr == ERROR_NO_MORE_FILES )
|
|
{
|
|
CWRg(RemoveDirectory(szPath));
|
|
hr=S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CWRg( DeleteFileA(szPath) );
|
|
}
|
|
|
|
Error:
|
|
return hr;
|
|
}
|