I am trying to get the DACL of service, and then get the SIDs. Here is my code:
PSECURITY_DESCRIPTOR psd = NULL;
DWORD dwSize = 0;
DWORD dwBytesNeeded = 0;
BOOL bDaclPresent = FALSE; // tu Trua mashin aq DACL
PACL pacl = NULL;
BOOL bDaclDefaulted = FALSE;
PEXPLICIT_ACCESS bevri = NULL;
ULONG aq = 0;
char ** gio = NULL;
serviceManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
SC_HANDLE me = OpenService(serviceManager, serviceName, READ_CONTROL);
if (serviceManager == NULL)
{
fprintf(fp, "OpenService: fail %d\n.\n", GetLastError());
fflush(fp);
}
if (!QueryServiceObjectSecurity(me, DACL_SECURITY_INFORMATION, &psd, 0, &dwBytesNeeded))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
dwSize = dwBytesNeeded;
psd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
if (psd == NULL)
{
fprintf(fp, "HeapAlloc failed\n");
fflush(fp);
}
if (!QueryServiceObjectSecurity(me, DACL_SECURITY_INFORMATION, psd, dwSize, &dwBytesNeeded))
{
fprintf(fp, "QueryServiceObjectSecurity failed %d\n", (int)GetLastError());
fflush(fp);
}
}
else
{
fprintf(fp, "QueryServiceObjectSecurity failed %d\n", (int)GetLastError());
fflush(fp);
}
}
if (!GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl, &bDaclDefaulted))
{
fprintf(fp, "GetSecurityDescriptorDacl failed %d\n", (int)GetLastError());
fflush(fp);
}
if (GetExplicitEntriesFromAcl(pacl, &aq, &bevri) != ERROR_SUCCESS)
{
fprintf(fp, "GetExplicitEntriesFromAcl: failed %d.\n", (int)GetLastError());
fflush(fp);
}
for (ULONG i = 0; i < aq; i++)
{
if (ConvertSidToStringSid(&bevri->Trustee.ptstrName[GetTrusteeForm(&bevri->Trustee)], gio) == 0)
{
fprintf(fp, "ConvertSidToStringSid: failed %d.\n", (int)GetLastError());
fflush(fp);
}
for (int index = 0; gio[index] != NULL; index++)
{
char * myString = gio[index];
fprintf(fp, "Value: %s\n",myString);
}
}
I've read in documentation that GetTrusteeForm function would indicate if Trustee has SID or name, it returned 0s which in TRUSTEE_FORM indicates to TRUSTEE_IS_SID. My problem is that I have ConvertSidToStringSid: failed 87. which is The parameter is incorrect.. I can't figure out why am I getting this. P.S. I'm sorry I know that this part of code is not really helpful to reproduce the issue, but I thought someone might knew what would problem be. Any help would be appriciated. Thanks.
Related
I need to verify an .exe and ensure the publisher name matches the expected name (not based on a key since that can change as new code signing certificates are issued, the name is always the same).
I found samples of using WinVerifyTrust to verify a signed .exe, but I also need the "Verified Publisher" that the UAC shows for signed executables. How do I get that using the Windows API functions in c or c++ ?
TIA!!
This is done by using WinVerifyTrust in conjunction with CryptQueryObject.
Please note, I did not write this code. I copied this from some site a while ago.. Probably Microsoft or a dev blog. You should simply be able to copy this in to a new C console project and compile/run it.
This is what it outputs:
#include <windows.h>
#include <wincrypt.h>
#include <wintrust.h>
#include <stdio.h>
#include <tchar.h>
#pragma comment(lib, "crypt32.lib")
#define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
typedef struct {
LPWSTR lpszProgramName;
LPWSTR lpszPublisherLink;
LPWSTR lpszMoreInfoLink;
} SPROG_PUBLISHERINFO, * PSPROG_PUBLISHERINFO;
BOOL GetProgAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo,
PSPROG_PUBLISHERINFO Info);
BOOL GetDateOfTimeStamp(PCMSG_SIGNER_INFO pSignerInfo, SYSTEMTIME* st);
BOOL PrintCertificateInfo(PCCERT_CONTEXT pCertContext);
BOOL GetTimeStampSignerInfo(PCMSG_SIGNER_INFO pSignerInfo,
PCMSG_SIGNER_INFO* pCounterSignerInfo);
int _tmain(int argc, TCHAR* argv[])
{
WCHAR szFileName[MAX_PATH];
HCERTSTORE hStore = NULL;
HCRYPTMSG hMsg = NULL;
PCCERT_CONTEXT pCertContext = NULL;
BOOL fResult;
DWORD dwEncoding, dwContentType, dwFormatType;
PCMSG_SIGNER_INFO pSignerInfo = NULL;
PCMSG_SIGNER_INFO pCounterSignerInfo = NULL;
DWORD dwSignerInfo;
CERT_INFO CertInfo;
SPROG_PUBLISHERINFO ProgPubInfo;
SYSTEMTIME st;
ZeroMemory(&ProgPubInfo, sizeof(ProgPubInfo));
__try
{
if (argc != 2)
{
_tprintf(_T("Usage: SignedFileInfo <filename>\n"));
return 0;
}
# ifdef UNICODE
lstrcpynW(szFileName, argv[1], MAX_PATH);
#else
if (mbstowcs(szFileName, argv[1], MAX_PATH) == -1)
{
printf("Unable to convert to unicode.\n");
__leave;
}
#endif
// Get message handle and store handle from the signed file.
fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
szFileName,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
CERT_QUERY_FORMAT_FLAG_BINARY,
0,
&dwEncoding,
&dwContentType,
&dwFormatType,
&hStore,
&hMsg,
NULL);
if (!fResult)
{
_tprintf(_T("CryptQueryObject failed with %x\n"), GetLastError());
__leave;
}
// Get signer information size.
fResult = CryptMsgGetParam(hMsg,
CMSG_SIGNER_INFO_PARAM,
0,
NULL,
&dwSignerInfo);
if (!fResult)
{
_tprintf(_T("CryptMsgGetParam failed with %x\n"), GetLastError());
__leave;
}
// Allocate memory for signer information.
pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
if (!pSignerInfo)
{
_tprintf(_T("Unable to allocate memory for Signer Info.\n"));
__leave;
}
// Get Signer Information.
fResult = CryptMsgGetParam(hMsg,
CMSG_SIGNER_INFO_PARAM,
0,
(PVOID)pSignerInfo,
&dwSignerInfo);
if (!fResult)
{
_tprintf(_T("CryptMsgGetParam failed with %x\n"), GetLastError());
__leave;
}
// Get program name and publisher information from
// signer info structure.
if (GetProgAndPublisherInfo(pSignerInfo, &ProgPubInfo))
{
if (ProgPubInfo.lpszProgramName != NULL)
{
wprintf(L"Program Name : %s\n",
ProgPubInfo.lpszProgramName);
}
if (ProgPubInfo.lpszPublisherLink != NULL)
{
wprintf(L"Publisher Link : %s\n",
ProgPubInfo.lpszPublisherLink);
}
if (ProgPubInfo.lpszMoreInfoLink != NULL)
{
wprintf(L"MoreInfo Link : %s\n",
ProgPubInfo.lpszMoreInfoLink);
}
}
_tprintf(_T("\n"));
// Search for the signer certificate in the temporary
// certificate store.
CertInfo.Issuer = pSignerInfo->Issuer;
CertInfo.SerialNumber = pSignerInfo->SerialNumber;
pCertContext = CertFindCertificateInStore(hStore,
ENCODING,
0,
CERT_FIND_SUBJECT_CERT,
(PVOID) & CertInfo,
NULL);
if (!pCertContext)
{
_tprintf(_T("CertFindCertificateInStore failed with %x\n"),
GetLastError());
__leave;
}
// Print Signer certificate information.
_tprintf(_T("Signer Certificate:\n\n"));
PrintCertificateInfo(pCertContext);
_tprintf(_T("\n"));
// Get the timestamp certificate signerinfo structure.
if (GetTimeStampSignerInfo(pSignerInfo, &pCounterSignerInfo))
{
// Search for Timestamp certificate in the temporary
// certificate store.
CertInfo.Issuer = pCounterSignerInfo->Issuer;
CertInfo.SerialNumber = pCounterSignerInfo->SerialNumber;
pCertContext = CertFindCertificateInStore(hStore,
ENCODING,
0,
CERT_FIND_SUBJECT_CERT,
(PVOID) & CertInfo,
NULL);
if (!pCertContext)
{
_tprintf(_T("CertFindCertificateInStore failed with %x\n"),
GetLastError());
__leave;
}
// Print timestamp certificate information.
_tprintf(_T("TimeStamp Certificate:\n\n"));
PrintCertificateInfo(pCertContext);
_tprintf(_T("\n"));
// Find Date of timestamp.
if (GetDateOfTimeStamp(pCounterSignerInfo, &st))
{
_tprintf(_T("Date of TimeStamp : %02d/%02d/%04d %02d:%02d\n"),
st.wMonth,
st.wDay,
st.wYear,
st.wHour,
st.wMinute);
}
_tprintf(_T("\n"));
}
}
__finally
{
// Clean up.
if (ProgPubInfo.lpszProgramName != NULL)
LocalFree(ProgPubInfo.lpszProgramName);
if (ProgPubInfo.lpszPublisherLink != NULL)
LocalFree(ProgPubInfo.lpszPublisherLink);
if (ProgPubInfo.lpszMoreInfoLink != NULL)
LocalFree(ProgPubInfo.lpszMoreInfoLink);
if (pSignerInfo != NULL) LocalFree(pSignerInfo);
if (pCounterSignerInfo != NULL) LocalFree(pCounterSignerInfo);
if (pCertContext != NULL) CertFreeCertificateContext(pCertContext);
if (hStore != NULL) CertCloseStore(hStore, 0);
if (hMsg != NULL) CryptMsgClose(hMsg);
}
return 0;
}
BOOL PrintCertificateInfo(PCCERT_CONTEXT pCertContext)
{
BOOL fReturn = FALSE;
LPTSTR szName = NULL;
DWORD dwData;
__try
{
// Print Serial Number.
_tprintf(_T("Serial Number: "));
dwData = pCertContext->pCertInfo->SerialNumber.cbData;
for (DWORD n = 0; n < dwData; n++)
{
_tprintf(_T("%02x "),
pCertContext->pCertInfo->SerialNumber.pbData[dwData - (n + 1)]);
}
_tprintf(_T("\n"));
// Get Issuer name size.
if (!(dwData = CertGetNameString(pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG,
NULL,
NULL,
0)))
{
_tprintf(_T("CertGetNameString failed.\n"));
__leave;
}
// Allocate memory for Issuer name.
szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
if (!szName)
{
_tprintf(_T("Unable to allocate memory for issuer name.\n"));
__leave;
}
// Get Issuer name.
if (!(CertGetNameString(pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG,
NULL,
szName,
dwData)))
{
_tprintf(_T("CertGetNameString failed.\n"));
__leave;
}
// print Issuer name.
_tprintf(_T("Issuer Name: %s\n"), szName);
LocalFree(szName);
szName = NULL;
// Get Subject name size.
if (!(dwData = CertGetNameString(pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
NULL,
0)))
{
_tprintf(_T("CertGetNameString failed.\n"));
__leave;
}
// Allocate memory for subject name.
szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
if (!szName)
{
_tprintf(_T("Unable to allocate memory for subject name.\n"));
__leave;
}
// Get subject name.
if (!(CertGetNameString(pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
szName,
dwData)))
{
_tprintf(_T("CertGetNameString failed.\n"));
__leave;
}
// Print Subject Name.
_tprintf(_T("Subject Name: %s\n"), szName);
fReturn = TRUE;
}
__finally
{
if (szName != NULL) LocalFree(szName);
}
return fReturn;
}
LPWSTR AllocateAndCopyWideString(LPCWSTR inputString)
{
LPWSTR outputString = NULL;
outputString = (LPWSTR)LocalAlloc(LPTR,
(wcslen(inputString) + 1) * sizeof(WCHAR));
if (outputString != NULL)
{
lstrcpyW(outputString, inputString);
}
return outputString;
}
BOOL GetProgAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo,
PSPROG_PUBLISHERINFO Info)
{
BOOL fReturn = FALSE;
PSPC_SP_OPUS_INFO OpusInfo = NULL;
DWORD dwData;
BOOL fResult;
__try
{
// Loop through authenticated attributes and find
// SPC_SP_OPUS_INFO_OBJID OID.
for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++)
{
if (lstrcmpA(SPC_SP_OPUS_INFO_OBJID,
pSignerInfo->AuthAttrs.rgAttr[n].pszObjId) == 0)
{
// Get Size of SPC_SP_OPUS_INFO structure.
fResult = CryptDecodeObject(ENCODING,
SPC_SP_OPUS_INFO_OBJID,
pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
0,
NULL,
&dwData);
if (!fResult)
{
_tprintf(_T("CryptDecodeObject failed with %x\n"),
GetLastError());
__leave;
}
// Allocate memory for SPC_SP_OPUS_INFO structure.
OpusInfo = (PSPC_SP_OPUS_INFO)LocalAlloc(LPTR, dwData);
if (!OpusInfo)
{
_tprintf(_T("Unable to allocate memory for Publisher Info.\n"));
__leave;
}
// Decode and get SPC_SP_OPUS_INFO structure.
fResult = CryptDecodeObject(ENCODING,
SPC_SP_OPUS_INFO_OBJID,
pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
0,
OpusInfo,
&dwData);
if (!fResult)
{
_tprintf(_T("CryptDecodeObject failed with %x\n"),
GetLastError());
__leave;
}
// Fill in Program Name if present.
if (OpusInfo->pwszProgramName)
{
Info->lpszProgramName =
AllocateAndCopyWideString(OpusInfo->pwszProgramName);
}
else
Info->lpszProgramName = NULL;
// Fill in Publisher Information if present.
if (OpusInfo->pPublisherInfo)
{
switch (OpusInfo->pPublisherInfo->dwLinkChoice)
{
case SPC_URL_LINK_CHOICE:
Info->lpszPublisherLink =
AllocateAndCopyWideString(OpusInfo->pPublisherInfo->pwszUrl);
break;
case SPC_FILE_LINK_CHOICE:
Info->lpszPublisherLink =
AllocateAndCopyWideString(OpusInfo->pPublisherInfo->pwszFile);
break;
default:
Info->lpszPublisherLink = NULL;
break;
}
}
else
{
Info->lpszPublisherLink = NULL;
}
// Fill in More Info if present.
if (OpusInfo->pMoreInfo)
{
switch (OpusInfo->pMoreInfo->dwLinkChoice)
{
case SPC_URL_LINK_CHOICE:
Info->lpszMoreInfoLink =
AllocateAndCopyWideString(OpusInfo->pMoreInfo->pwszUrl);
break;
case SPC_FILE_LINK_CHOICE:
Info->lpszMoreInfoLink =
AllocateAndCopyWideString(OpusInfo->pMoreInfo->pwszFile);
break;
default:
Info->lpszMoreInfoLink = NULL;
break;
}
}
else
{
Info->lpszMoreInfoLink = NULL;
}
fReturn = TRUE;
break; // Break from for loop.
} // lstrcmp SPC_SP_OPUS_INFO_OBJID
} // for
}
__finally
{
if (OpusInfo != NULL) LocalFree(OpusInfo);
}
return fReturn;
}
BOOL GetDateOfTimeStamp(PCMSG_SIGNER_INFO pSignerInfo, SYSTEMTIME* st)
{
BOOL fResult;
FILETIME lft, ft;
DWORD dwData;
BOOL fReturn = FALSE;
// Loop through authenticated attributes and find
// szOID_RSA_signingTime OID.
for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++)
{
if (lstrcmpA(szOID_RSA_signingTime,
pSignerInfo->AuthAttrs.rgAttr[n].pszObjId) == 0)
{
// Decode and get FILETIME structure.
dwData = sizeof(ft);
fResult = CryptDecodeObject(ENCODING,
szOID_RSA_signingTime,
pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
0,
(PVOID) & ft,
&dwData);
if (!fResult)
{
_tprintf(_T("CryptDecodeObject failed with %x\n"),
GetLastError());
break;
}
// Convert to local time.
FileTimeToLocalFileTime(&ft, &lft);
FileTimeToSystemTime(&lft, st);
fReturn = TRUE;
break; // Break from for loop.
} //lstrcmp szOID_RSA_signingTime
} // for
return fReturn;
}
BOOL GetTimeStampSignerInfo(PCMSG_SIGNER_INFO pSignerInfo, PCMSG_SIGNER_INFO* pCounterSignerInfo)
{
PCCERT_CONTEXT pCertContext = NULL;
BOOL fReturn = FALSE;
BOOL fResult;
DWORD dwSize;
__try
{
*pCounterSignerInfo = NULL;
// Loop through unathenticated attributes for
// szOID_RSA_counterSign OID.
for (DWORD n = 0; n < pSignerInfo->UnauthAttrs.cAttr; n++)
{
if (lstrcmpA(pSignerInfo->UnauthAttrs.rgAttr[n].pszObjId,
szOID_RSA_counterSign) == 0)
{
// Get size of CMSG_SIGNER_INFO structure.
fResult = CryptDecodeObject(ENCODING,
PKCS7_SIGNER_INFO,
pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].pbData,
pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].cbData,
0,
NULL,
&dwSize);
if (!fResult)
{
_tprintf(_T("CryptDecodeObject failed with %x\n"),
GetLastError());
__leave;
}
// Allocate memory for CMSG_SIGNER_INFO.
*pCounterSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSize);
if (!*pCounterSignerInfo)
{
_tprintf(_T("Unable to allocate memory for timestamp info.\n"));
__leave;
}
// Decode and get CMSG_SIGNER_INFO structure
// for timestamp certificate.
fResult = CryptDecodeObject(ENCODING,
PKCS7_SIGNER_INFO,
pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].pbData,
pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].cbData,
0,
(PVOID) * pCounterSignerInfo,
&dwSize);
if (!fResult)
{
_tprintf(_T("CryptDecodeObject failed with %x\n"),
GetLastError());
__leave;
}
fReturn = TRUE;
break; // Break from for loop.
}
}
}
__finally
{
// Clean up.
if (pCertContext != NULL) CertFreeCertificateContext(pCertContext);
}
return fReturn;
}
my pc is OS: windows10 x64.
i want to enable / disable virtual com port using code.
actually, error is happened below,
errorcode = #define ERROR_ACCESS_DENIED 5L
in window10, i cannot not control device disable or enable ???
or source code is wrong ??
if you know that, please help me
used code is below. that is get from stackoverflow.com
bool COhCoachView::ControlDeviceDriver(bool bStatus) {
IN LPTSTR HardwareId;
//HardwareId = L"DAUDIO\\FUNC_01&VEN_10DE&DEV_0018&SUBSYS_10DE0101";
// dock device name : \\?\USB#VID_0462&PID_5740#00000000001A#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
CString debug;
char* ptr;
::SendMessage(hwndLogBar, MSG_WRITE_LOG, 0, (LPARAM)(LPCTSTR)"ControlDeviceDriver");
DWORD NewState;
if (bStatus) {
NewState = DICS_ENABLE;
}
else {
NewState = DICS_DISABLE;
}
DWORD i, err;
bool found = false;
HDEVINFO hDevInfo;
SP_DEVINFO_DATA spDevInfoData;
hDevInfo = SetupDiGetClassDevs(NULL, 0, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
printf("blad1");
return false;
}
spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++)
{
DWORD DataT;
LPTSTR p, buffer = NULL;
DWORD buffersize = 0;
// get all devices info
while (!SetupDiGetDeviceRegistryProperty(hDevInfo,
&spDevInfoData,
SPDRP_HARDWAREID,
&DataT,
(PBYTE)buffer,
buffersize,
&buffersize))
{
if (GetLastError() == ERROR_INVALID_DATA) {
break;
}
else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
if (buffer)
LocalFree(buffer);
buffer = (TCHAR*)LocalAlloc(LPTR, buffersize);
}
else {
goto cleanup_DeviceInfo;
}
}
if (GetLastError() == ERROR_INVALID_DATA)
continue;
ptr = strstr(buffer, "VID_0462&PID_5740");
if (ptr != NULL)
{
debug.Format("device name: %s", buffer);
::SendMessage(hwndLogBar, MSG_WRITE_LOG, 0, (LPARAM)(LPCTSTR)debug);
found = true;
}
//find device with HardwerId
/*
for (p = buffer; *p && (p < &buffer[buffersize]); p += lstrlen(p) + sizeof(TCHAR)) {
//debug.Format("device name: %s", p);
//::SendMessage(hwndLogBar, MSG_WRITE_LOG, 0, (LPARAM)(LPCTSTR)debug);
if (!_tcscmp(HardwareId, p)) {
found = true;
break;
}
}
*/
if (buffer)
LocalFree(buffer);
// if device found change it's state
if (found)
{
SP_PROPCHANGE_PARAMS params;
params.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
params.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
params.Scope = DICS_FLAG_GLOBAL;
params.StateChange = NewState;
// setup proper parameters
if (!SetupDiSetClassInstallParams(hDevInfo, &spDevInfoData, ¶ms.ClassInstallHeader, sizeof(params))) {
DWORD errorcode = GetLastError();
debug.Format("==== error %x ======", errorcode);
::SendMessage(hwndLogBar, MSG_WRITE_LOG, 0, (LPARAM)(LPCTSTR)debug);
}
// use parameters
if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, &spDevInfoData)) {
DWORD errorcode = GetLastError(); // error here
if (errorcode == 0x05)
{
for (int i = 0; i < 5; i++)
{
if (SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, &spDevInfoData))
{
::SendMessage(hwndLogBar, MSG_WRITE_LOG, 0, (LPARAM)(LPCTSTR)"retry succeeded for disabling device");
break;
}
::SendMessage(hwndLogBar, MSG_WRITE_LOG, 0, (LPARAM)(LPCTSTR)"retry failed for disabling device");
Sleep(20);
}
}
debug.Format("==== error2 %x ======", errorcode);
::SendMessage(hwndLogBar, MSG_WRITE_LOG, 0, (LPARAM)(LPCTSTR)debug);
}
switch (NewState) {
case DICS_DISABLE:
::SendMessage(hwndLogBar, MSG_WRITE_LOG, 0, (LPARAM)(LPCTSTR)"Device OFF");
printf("off");
break;
case DICS_ENABLE:
::SendMessage(hwndLogBar, MSG_WRITE_LOG, 0, (LPARAM)(LPCTSTR)"Device ON");
printf("on");
break;
}
break;
}
}
cleanup_DeviceInfo:
err = GetLastError();
SetupDiDestroyDeviceInfoList(hDevInfo);
SetLastError(err);
return true;
return true;
}
thanks a lot
My Env:
Qt 5.3.1
Windows 10
I need to find the path of mounted USB storage devices.
Through the path, I can copy the files via Qt.
I know there is a cross-platform libusb. But want to know any simple solution.
First you need to get removable drives:
void EnumUsbDrives() {
DWORD drv = ::GetLogicalDrives();
if (drv == 0) return;
DWORD mask = 1;
TCHAR szDrive[] = _TEXT("?:\\");
for (uint_t i = 0; i < ('Z' - 'A' + 1); i++, mask <<= 1) {
if (drv & mask) {
szDrive[0] = (TCHAR)(_T('A') + i);
if (::GetDriveType(szDrive) == DRIVE_REMOVABLE) {
bool bUSB = IsDriveUSB(szDrive);
if (bUSB) {
// Time do to something useful
}
}
}
}
}
Function IsDriveUSB is a bit more complicated. I have teared it from an in-house library; the function uses custom helper classes xregistry and xstring_nocase. Their purpose is pretty obvious, I believe you will have no trouble replacing it with other similar classes or API calls.
bool IsDriveUSB (LPCTSTR szDrive) throw() {
TCHAR szLogicalDrive[] = _TEXT("\\\\.\\x:");
szLogicalDrive[4] = szDrive[0];
HANDLE hDrive = ::CreateFile(szLogicalDrive, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hDrive == INVALID_HANDLE_VALUE) return false; // Can't open drive so we have to assume the drive is fixed
VOLUME_DISK_EXTENTS vde;
DWORD dwBytesReturned = 0;
BOOL br = ::DeviceIoControl(hDrive, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &vde, sizeof(vde), &dwBytesReturned, NULL);
::CloseHandle(hDrive);
if (!br) return false; // Can't get extents info so we have to assume the drive is fixed
if (vde.NumberOfDiskExtents != 1) return false;
ULONG uPhysDrive = vde.Extents[0].DiskNumber;
TCHAR szPhysDrive[16];
_stprintf(szPhysDrive, _TEXT("%u"), uPhysDrive);
try {
xregistry rk(HKEY_LOCAL_MACHINE, OS.Is64bit());
rk.open(_TEXT("SYSTEM\\CurrentControlSet\\services\\Disk\\Enum"), KEY_QUERY_VALUE);
if (!rk.value_exists(szPhysDrive)) return false;
xstring_nocase strInterface = rk.get_string(szPhysDrive).substring(0, 7);
return strInterface == _TEXT("USBSTOR");
}
catch (...) {
return false;
}
}
first we need enumerate all devices which support interface GUID_DEVINTERFACE_DISK. then we can open file on this interface and query for it STORAGE_ADAPTER_DESCRIPTOR or STORAGE_DEVICE_DESCRIPTOR and look for
BusType
Specifies a value of type STORAGE_BUS_TYPE that indicates the
type of the bus to which the device is connected.
for usb this will be BusTypeUsb
static volatile UCHAR guz;
CONFIGRET EnumUsbStor()
{
CONFIGRET err;
PVOID stack = alloca(guz);
ULONG BufferLen = 0, NeedLen = 256;
union {
PVOID buf;
PWSTR pszDeviceInterface;
};
for(;;)
{
if (BufferLen < NeedLen)
{
BufferLen = RtlPointerToOffset(buf = alloca((NeedLen - BufferLen) * sizeof(WCHAR)), stack) / sizeof(WCHAR);
}
switch (err = CM_Get_Device_Interface_ListW(const_cast<PGUID>(&GUID_DEVINTERFACE_DISK),
0, pszDeviceInterface, BufferLen, CM_GET_DEVICE_INTERFACE_LIST_PRESENT))
{
case CR_BUFFER_SMALL:
if (err = CM_Get_Device_Interface_List_SizeW(&NeedLen, const_cast<PGUID>(&GUID_DEVINTERFACE_DISK),
0, CM_GET_DEVICE_INTERFACE_LIST_PRESENT))
{
default:
return err;
}
continue;
case CR_SUCCESS:
while (*pszDeviceInterface)
{
BOOLEAN bIsUsb = FALSE;
HANDLE hFile = CreateFile(pszDeviceInterface, 0, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
STORAGE_PROPERTY_QUERY spq = { StorageAdapterProperty, PropertyStandardQuery };
STORAGE_ADAPTER_DESCRIPTOR sad;
ULONG n;
if (DeviceIoControl(hFile, IOCTL_STORAGE_QUERY_PROPERTY, &spq, sizeof(spq), &sad, sizeof(sad), &n, 0))
{
bIsUsb = sad.BusType == BusTypeUsb;
}
CloseHandle(hFile);
}
pszDeviceInterface += 1 + wcslen(pszDeviceInterface);
}
return 0;
}
}
}
also we can look for EnumeratorName in interface string - are this is USBSTOR. fast end simply:
wcsstr(_wcsupr(pszDeviceInterface), L"\\USBSTOR#");
search for \USBSTOR# substring in interface name. or more correct - get Device_InstanceId from interface name and query it for DEVPKEY_Device_EnumeratorName
CONFIGRET IsUsbStor(DEVINST dnDevInst, BOOLEAN& bUsbStor)
{
ULONG cb = 0, rcb = 256;
PVOID stack = alloca(guz);
DEVPROPTYPE PropertyType;
CONFIGRET status;
union {
PVOID pv;
PWSTR EnumeratorName;
PBYTE pb;
};
do
{
if (cb < rcb)
{
rcb = cb = RtlPointerToOffset(pv = alloca(rcb - cb), stack);
}
status = CM_Get_DevNode_PropertyW(dnDevInst, &DEVPKEY_Device_EnumeratorName, &PropertyType,
pb, &rcb, 0);
if (status == CR_SUCCESS)
{
if (PropertyType == DEVPROP_TYPE_STRING)
{
DbgPrint("EnumeratorName = %S\n", EnumeratorName);
bUsbStor = !_wcsicmp(L"USBSTOR", EnumeratorName);
}
else
{
status = CR_WRONG_TYPE;
}
break;
}
} while (status == CR_BUFFER_SMALL);
return status;
}
CONFIGRET IsUsbStor(PCWSTR pszDeviceInterface, BOOLEAN& bUsbStor)
{
ULONG cb = 0, rcb = 256;
PVOID stack = alloca(guz);
DEVPROPTYPE PropertyType;
CONFIGRET status;
union {
PVOID pv;
PWSTR DeviceID;
PBYTE pb;
};
do
{
if (cb < rcb)
{
rcb = cb = RtlPointerToOffset(pv = alloca(rcb - cb), stack);
}
status = CM_Get_Device_Interface_PropertyW(pszDeviceInterface, &DEVPKEY_Device_InstanceId, &PropertyType, pb, &rcb, 0);
if (status == CR_SUCCESS)
{
if (PropertyType == DEVPROP_TYPE_STRING)
{
DbgPrint("DeviceID = %S\n", DeviceID);
DEVINST dnDevInst;
status = CM_Locate_DevNodeW(&dnDevInst, DeviceID, CM_LOCATE_DEVNODE_NORMAL);
if (status == CR_SUCCESS)
{
status = IsUsbStor(dnDevInst, bUsbStor);
}
}
else
{
status = CR_WRONG_TYPE;
}
break;
}
} while (status == CR_BUFFER_SMALL);
return status;
}
need information about the buttons of the device, how many, etc.
I tried iokit but got a strange list
name = IOUSBRootHubDevice
name = IOUSBHubDevice
name = IOUSBDevice
name = IOUSBHubDevice
name = IOUSBDevice
name = IOUSBRootHubDevice
name = IOUSBHubDevice
name = IOUSBDevice
name = IOUSBDevice
name = IOUSBDevice
my code
CFMutableDictionaryRef matchingDict;
io_iterator_t iter;
kern_return_t kr;
io_service_t device;
io_name_t name;
//io_object_t device;
/* set up a matching dictionary for the class */
matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
if (matchingDict == NULL){
return -1; // fail
}
/* Now we have a dictionary, get an iterator.*/
kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
if (kr != KERN_SUCCESS){
return -1;
}
/* iterate */
while ((device = IOIteratorNext(iter))){
IOObjectGetClass(device, name);
printf("name = %s \n", name);
/* do something with device, eg. check properties */
/* ... */
/* And free the reference taken before continuing to the next item */
IOObjectRelease(device);
}
/* Done, release the iterator */
IOObjectRelease(iter);
there are probably a better option, but I can not find in google
turned himself in, as it so
static void MyCreateHIDDeviceInterface(io_object_t hidDevice,
IOHIDDeviceInterface122 ***hidDeviceInterface)
{
io_name_t className;
IOCFPlugInInterface **plugInInterface = NULL;
HRESULT plugInResult = S_OK;
SInt32 score = 0;
IOReturn ioReturnValue = kIOReturnSuccess;
ioReturnValue = IOObjectGetClass(hidDevice, className);
printf("Failed to get class name.\n");//print_errmsg_if_io_err(ioReturnValue, "Failed to get class name.");
printf("Found device type %s\n", className);
ioReturnValue = IOCreatePlugInInterfaceForService(hidDevice,
kIOHIDDeviceUserClientTypeID,
kIOCFPlugInInterfaceID,
&plugInInterface,
&score);
if (ioReturnValue == kIOReturnSuccess)
{
//Call a method of the intermediate plug-in to create the device
//interface
plugInResult = (*plugInInterface)->QueryInterface(plugInInterface,
CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID),
(LPVOID *) hidDeviceInterface);
printf("Couldn't create HID class device interface.\n");//print_errmsg_if_err(plugInResult != S_OK, "Couldn't create HID class device interface");
IODestroyPlugInInterface(plugInInterface);
//(*plugInInterface)->Release(plugInInterface);
}
}
void getCookies(IOHIDDeviceInterface122** deviceInterface){
CFArrayRef elements;
CFDictionaryRef element;
CFTypeRef object;
long number;
long usagePage;
long usage;
IOHIDElementCookie cookie;
(*deviceInterface)->copyMatchingElements(deviceInterface, NULL, &elements);
for ( CFIndex i=0; i<CFArrayGetCount(elements); i++ ){
element = (CFDictionaryRef)CFArrayGetValueAtIndex(elements, i);
// Get usage page
object = CFDictionaryGetValue(element, CFSTR(kIOHIDElementUsagePageKey));
if( object==0 || CFGetTypeID(object) != CFNumberGetTypeID() ){
continue;
}
if( !CFNumberGetValue((CFNumberRef) object, kCFNumberLongType, &number) ){
continue;
}
usagePage = number;
if( usagePage!=kHIDPage_GenericDesktop && usagePage!=kHIDPage_Button ){
continue;
}
// Get usage
object = CFDictionaryGetValue( element, CFSTR(kIOHIDElementUsageKey) );
if( object==0 || CFGetTypeID(object) != CFNumberGetTypeID() ){
continue;
}
if( !CFNumberGetValue((CFNumberRef) object, kCFNumberLongType, &number) ){
continue;
}
usage = number;
// Get cookie
object = CFDictionaryGetValue( element, CFSTR(kIOHIDElementCookieKey) );
if( object==0 || CFGetTypeID(object) != CFNumberGetTypeID() ){
continue;
}
if( !CFNumberGetValue((CFNumberRef) object, kCFNumberLongType, &number) ){
continue;
}
cookie = (IOHIDElementCookie) number;
if(usagePage == kHIDPage_GenericDesktop){
switch( usage )
{
case kHIDUsage_GD_Pointer: {
printf("kHIDUsage_GD_Pointer \n");
break;
}
case kHIDUsage_GD_Mouse: {
printf("kHIDUsage_GD_Mouse \n");
break;
};
case kHIDUsage_GD_Joystick: {
printf("kHIDUsage_GD_Joystick \n");
break;
}
case kHIDUsage_GD_GamePad: {
printf("kHIDUsage_GD_GamePad \n");
break;
}
case kHIDUsage_GD_Keyboard:{
printf("kHIDUsage_GD_Keyboard \n");
break;
};
case kHIDUsage_GD_Keypad: {
printf("kHIDUsage_GD_Keypad \n");
break;
};
case kHIDUsage_GD_MultiAxisController:{
printf("kHIDUsage_GD_MultiAxisController \n");
break;
};
case kHIDUsage_GD_X: {
printf("kHIDUsage_GD_X \n");
break;
};
case kHIDUsage_GD_Y: {
printf("kHIDUsage_GD_Y \n");
break;
};
}
} else if( usagePage == kHIDPage_Button){
printf("kHIDPage_Button \n");
}
}
}
int main(int argc, const char * argv[])
{
CFMutableDictionaryRef matchingDict;
io_iterator_t iter;
kern_return_t kr;
io_object_t device;
char name[128];
IOHIDDeviceInterface122 **deviceInterface = NULL;
/* set up a matching dictionary for the class */
matchingDict = IOServiceMatching(kIOHIDDeviceKey);//kIOHIDDeviceKey
if (matchingDict == NULL)
{
return -1; // fail
}
/* Now we have a dictionary, get an iterator.*/
kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
if (kr != KERN_SUCCESS)
{
return -1;
}
/* iterate */
while ((device = IOIteratorNext(iter)))
{
IOObjectGetClass(device, name);
if(!strcmp(name,"BNBMouseDevice")){
MyCreateHIDDeviceInterface(device, &deviceInterface);
if(*deviceInterface != NULL){
getCookies(deviceInterface);
(*deviceInterface)->Release(deviceInterface);
}
printf("name = %s \n \n", name);
}else if(!strcmp(name,"AppleBluetoothHIDKeyboard")){
MyCreateHIDDeviceInterface(device, &deviceInterface);
if(*deviceInterface != NULL){
getCookies(deviceInterface);
(*deviceInterface)->Release(deviceInterface);
}
printf("name = %s \n \n", name);
}else if(!strcmp(name,"IOUSBHIDDriver")){
MyCreateHIDDeviceInterface(device, &deviceInterface);
if(*deviceInterface != NULL){
getCookies(deviceInterface);
(*deviceInterface)->Release(deviceInterface);
}
printf("name = %s \n \n", name);
}
IOObjectRelease(device);
}
/* Done, release the iterator */
IOObjectRelease(iter);
return 0;
}
here it is my code through which I am successfully initialize the VDS service and get the Packs but When I call QueryVolumes on IVdsPack Object, I am able to get IEnumVdsObjects but unable to get IUnknown* array through IEnumVdsObject::Next method, it reutrns S_FALSE with IUnkown* = NULL. So this IUnknown* cant be used to QueryInterface for IVdsVolume
Below is my code
HRESULT hResult;
IVdsService* pService = NULL;
IVdsServiceLoader *pLoader = NULL;
//Launch the VDS Service
hResult = CoInitialize(NULL);
if( SUCCEEDED(hResult) )
{
hResult = CoCreateInstance(
CLSID_VdsLoader,
NULL,
CLSCTX_LOCAL_SERVER,
IID_IVdsServiceLoader,
(void**) &pLoader
);
//if succeeded load VDS on local machine
if( SUCCEEDED(hResult) )
pLoader->LoadService(NULL, &pService);
//Done with Loader now release VDS Loader interface
_SafeRelease(pLoader);
if( SUCCEEDED(hResult) )
{
hResult = pService->WaitForServiceReady();
if ( SUCCEEDED(hResult) )
{
AfxMessageBox(L"VDS Service Loaded");
IEnumVdsObject* pEnumVdsObject = NULL;
hResult = pService->QueryProviders(VDS_QUERY_SOFTWARE_PROVIDERS, &pEnumVdsObject);
IUnknown* ppObjUnk ;
IVdsSwProvider* pVdsSwProvider = NULL;
IVdsPack* pVdsPack = NULL;
IVdsVolume* pVdsVolume = NULL;
ULONG ulFetched = 0;
hResult = E_INVALIDARG;
while(!SUCCEEDED(hResult))
{
hResult = pEnumVdsObject->Next(1, &ppObjUnk, &ulFetched);
hResult = ppObjUnk->QueryInterface(IID_IVdsSwProvider, (void**)&pVdsSwProvider);
if(!SUCCEEDED(hResult))
_SafeRelease(ppObjUnk);
}
_SafeRelease(pEnumVdsObject);
_SafeRelease(ppObjUnk);
hResult = pVdsSwProvider->QueryPacks(&pEnumVdsObject);
hResult = E_INVALIDARG;
while(!SUCCEEDED(hResult))
{
hResult = pEnumVdsObject->Next(1, &ppObjUnk, &ulFetched);
hResult = ppObjUnk->QueryInterface(IID_IVdsPack, (void**)&pVdsPack);
if(!SUCCEEDED(hResult))
_SafeRelease(ppObjUnk);
}
_SafeRelease(pEnumVdsObject);
_SafeRelease(ppObjUnk);
hResult = pVdsPack->QueryVolumes(&pEnumVdsObject);
pEnumVdsObject->Reset();
hResult = E_INVALIDARG;
ulFetched = 0;
BOOL bDone = FALSE;
while(!SUCCEEDED(hResult))
{
hResult = pEnumVdsObject->Next(1, &ppObjUnk, &ulFetched);
//hResult = ppObjUnk->QueryInterface(IID_IVdsVolume, (void**)&pVdsVolume);
if(!SUCCEEDED(hResult))
_SafeRelease(ppObjUnk);
}
_SafeRelease(pEnumVdsObject);
_SafeRelease(ppObjUnk);
_SafeRelease(pVdsPack);
_SafeRelease(pVdsSwProvider);
// hResult = pVdsVolume->AddAccessPath(TEXT("G:\\"));
if(SUCCEEDED(hResult))
AfxMessageBox(L"Add Access Path Successfully");
else
AfxMessageBox(L"Unable to Add access path");
//UUID of IVdsVolumeMF {EE2D5DED-6236-4169-931D-B9778CE03DC6}
static const GUID GUID_IVdsVolumeMF = {0xEE2D5DED, 0x6236, 4169,{0x93, 0x1D, 0xB9, 0x77, 0x8C, 0xE0, 0x3D, 0XC6} };
hResult = pService->GetObject(GUID_IVdsVolumeMF, VDS_OT_VOLUME, &ppObjUnk);
if(hResult == VDS_E_OBJECT_NOT_FOUND)
AfxMessageBox(L"Object Not found");
if(hResult == VDS_E_INITIALIZED_FAILED)
AfxMessageBox(L"Initialization failed");
// pVdsVolume = reinterpret_cast<IVdsVolumeMF*>(ppObjUnk);
if(SUCCEEDED(hResult))
{
// hResult = pVdsVolume->AddAccessPath(TEXT("G:\\"));
if(SUCCEEDED(hResult))
{
IVdsAsync* ppVdsSync;
AfxMessageBox(L"Formatting is about to Start......");
// hResult = pVdsVolume->Format(VDS_FST_UDF, TEXT("UDF_FORMAT_TEST"), 2048, TRUE, FALSE, FALSE, &ppVdsSync);
if(SUCCEEDED(hResult))
AfxMessageBox(L"Formatting Started.......");
else
AfxMessageBox(L"Formatting Failed");
}
else
AfxMessageBox(L"Unable to Add Access Path");
}
_SafeRelease(pVdsVolume);
}
else
{
AfxMessageBox(L"VDS Service Cannot be Loaded");
}
}
}
_SafeRelease(pService);
You need to move your other loops inside your while loop that enumerates your IVdsSwProviders.
I modified your code for my own purpose. You have to be careful because I threw it together for a test and therefore didn't care about memory leaks and freeing COM objects. I also have a lot of debug prints in there too:
#include "stdafx.h"
#include "initguid.h"
#include <vds.h>
#include <stdio.h>
#pragma comment( lib, "ole32.lib" )
#pragma comment( lib, "rpcrt4.lib" )
#define _SafeRelease(x) {if (NULL != x) { x->Release(); x = NULL; } }
void EnumerateDisks(IVdsPack* pPack)
{
HRESULT hResult;
ULONG ulFetched = 0;
IUnknown* ppObjUnk ;
IEnumVdsObject* pEnumVdsObject = NULL;
IVdsDisk* pVdsDisk = NULL;
IVdsDisk2* pVdsDisk2 = NULL;
IVdsAdvancedDisk* pVdsAdvancedDisk = NULL;
if (pPack == 0)
return;
hResult = pPack->QueryDisks(&pEnumVdsObject);
if (pEnumVdsObject == 0)
return;
while( true)
{
if (!pEnumVdsObject)
break;
hResult = pEnumVdsObject->Next(1, &ppObjUnk, &ulFetched);
if (ulFetched == 0) break;
hResult = ppObjUnk->QueryInterface(IID_IVdsDisk, (void**)&pVdsDisk);
VDS_DISK_PROP diskProp;
pVdsDisk->GetProperties(&diskProp);
printf("----------------------------------------\n");
wprintf(L"disk: %d\n", diskProp.status);
wprintf(L"disk: %s\n", diskProp.pwszAdaptorName);
wprintf(L"disk: %s\n", diskProp.pwszDevicePath);
wprintf(L"disk: %s\n", diskProp.pwszFriendlyName);
wprintf(L"disk: %s\n", diskProp.pwszName);
wprintf(L"disk: %d\n", diskProp.dwDeviceType);
wprintf(L"disk: %d\n", diskProp.dwMediaType);
wprintf(L"disk: %d\n", diskProp.dwSignature);
wprintf(L"disk: %d\n", diskProp.PartitionStyle);
wprintf(L"disk: %d\n", diskProp.ReserveMode);
wprintf(L"disk: %d\n", diskProp.ulFlags);
VDS_PARTITION_PROP * pPropArray = NULL;
LONG pNumberOfPartitions = 0;
hResult = ppObjUnk->QueryInterface(IID_IVdsAdvancedDisk, (void**)&pVdsAdvancedDisk);
pVdsAdvancedDisk->QueryPartitions(&pPropArray, &pNumberOfPartitions);
VDS_PARTITION_PROP * tmp = pPropArray;
for (int i = 0; i < pNumberOfPartitions; ++i)
{
printf("Number: %d\n", tmp->ulPartitionNumber);
printf("Style : %d\n", tmp->PartitionStyle);
printf("Flags : %d\n", tmp->ulFlags);
printf("Offset: %ull\n", tmp->ullOffset);
printf("Size: %ull\n", tmp->ullSize);
printf("MBR type: %d\n", tmp->Mbr.partitionType);
printf("MBR type: %d\n", tmp->Mbr.bootIndicator);
printf("MBR type: %d\n", tmp->Mbr.recognizedPartition);
printf("MBR type: %d\n", tmp->Mbr.hiddenSectors);
++tmp;
}
CoTaskMemFree(pPropArray);
}
}
void EnumerateVolumes(IVdsPack* pPack)
{
HRESULT hResult;
ULONG ulFetched = 0;
IUnknown* ppObjUnk ;
IEnumVdsObject* pEnumVdsObject = NULL;
IVdsVolume* pVdsVolume = NULL;
if (pPack == 0)
return;
hResult = pPack->QueryVolumes(&pEnumVdsObject);
if (pEnumVdsObject == 0)
return;
while( true)
{
hResult = pEnumVdsObject->Next(1, &ppObjUnk, &ulFetched);
if (ulFetched == 0) break;
hResult = ppObjUnk->QueryInterface(IID_IVdsVolume, (void**)&pVdsVolume);
VDS_VOLUME_PROP volProp;
pVdsVolume->GetProperties(&volProp);
printf("Vol name : %S\n", volProp.pwszName);
printf("Vol health: %d\n", volProp.health);
}
}
void EnumeratePacks(IVdsSwProvider* pProvider)
{
HRESULT hResult;
ULONG ulFetched = 0;
IUnknown* ppObjUnk ;
IEnumVdsObject* pEnumVdsObject = NULL;
IVdsPack* pVdsPack = NULL;
if (pProvider == 0)
return;
hResult = pProvider->QueryPacks(&pEnumVdsObject);
if (pEnumVdsObject == 0)
return;
while( true)
{
hResult = pEnumVdsObject->Next(1, &ppObjUnk, &ulFetched);
if (ulFetched == 0) break;
hResult = ppObjUnk->QueryInterface(IID_IVdsPack, (void**)&pVdsPack);
VDS_PACK_PROP packProp;
pVdsPack->GetProperties(&packProp);
if (packProp.status == VDS_PS_ONLINE) {
printf("Pack name : %S\n", packProp.pwszName);
printf("Pack status: %d\n", packProp.status);
printf("Pack flags : %d\n", packProp.ulFlags);
EnumerateDisks(pVdsPack);
EnumerateVolumes(pVdsPack);
}
}
}
void EnumerateSoftwareProviders(IVdsService* pService)
{
HRESULT hResult;
ULONG ulFetched = 0;
IUnknown* ppObjUnk ;
IEnumVdsObject* pEnumVdsObject = NULL;
IVdsSwProvider* pVdsSwProvider = NULL;
hResult = pService->QueryProviders(VDS_QUERY_SOFTWARE_PROVIDERS, &pEnumVdsObject);
while( true)
{
hResult = pEnumVdsObject->Next(1, &ppObjUnk, &ulFetched);
if (ulFetched == 0) break;
hResult = ppObjUnk->QueryInterface(IID_IVdsSwProvider,(void**)&pVdsSwProvider);
EnumeratePacks(pVdsSwProvider);
}
}
int __cdecl main(void)
{
//////////////////////////////////////////////////////////////////
HRESULT hResult;
IVdsService* pService = NULL;
IVdsServiceLoader *pLoader = NULL;
//Launch the VDS Service
hResult = CoInitializeEx(NULL, COINIT_MULTITHREADED);
// Initialize COM security
CoInitializeSecurity(
NULL, // Allow *all* VSS writers to communicate back!
-1, // Default COM authentication service
NULL, // Default COM authorization service
NULL, // reserved parameter
RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // Strongest COM authentication level
RPC_C_IMP_LEVEL_IMPERSONATE, // Minimal impersonation abilities
NULL, // Default COM authentication settings
EOAC_NONE, // No special options
NULL // Reserved parameter
);
if( SUCCEEDED(hResult) )
{
hResult = CoCreateInstance(
CLSID_VdsLoader,
NULL,
CLSCTX_LOCAL_SERVER,
IID_IVdsServiceLoader,
(void**) &pLoader
);
//if succeeded load VDS on local machine
if( SUCCEEDED(hResult) )
pLoader->LoadService(NULL, &pService);
//Done with Loader now release VDS Loader interface
_SafeRelease(pLoader);
if( SUCCEEDED(hResult) )
{
hResult = pService->WaitForServiceReady();
if ( SUCCEEDED(hResult) )
{
EnumerateSoftwareProviders(pService);
return 0;
}
}
}
return -1;
}