// // 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 #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; i2); 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; }