How to predeliver WMA DRM licenses? - c++

I'm trying to install WMA DRM licenses files silently so that users would not have to play each song and acknowledge for each license.
I figured out that I need to do something like this :
HRESULT res = CoCreateInstance(__uuidof(RMGetLicense),NULL,CLSCTX_ALL,__uuidof(IRMGetLicense ),(void**) &pLicense );
res = pLicense->GetLicenseFromURL(NULL, bstrURL);
The bstrURL is expected to contain a keyID as a parameter, which allow to retrieve the file matching with the music file. I can't find how to get this keyID back from the WMA file.
I may get the problem wrongly though. Am I in the good way ?

You have to pass header object as a first parameter. More information is in MSDN

Related

Determining the format of audio file (MP3) using SAPI

HiI'm trying to create a "Speech to text" app that can transcribe any audio/video file. I've created an app based on this post and it works great for WAV files. But if I use an MP3 file, the line hr = cpInputStream->BindToFile(wInputFileName.c_str(), SPFM_OPEN_READONLY, &sInputFormat.FormatId(), sInputFormat.WaveFormatExPtr(), SPFEI_ALL_EVENTS); returns
The Parameter is incorrect
The question is, can I use MP3 files as input for SAPI? and if yes, how do I determine the correct format for the call to hr = sInputFormat.AssignFormat(SPSF_16kHz16BitStereo) because SPSF_16kHz16BitStereo will certainly not be correct and I don't think we should hardcode it.

How to get file date Accessed?

I'm looking for this function from std::filesystem but can't figure it out.
How to access this information?
Only write time (Modified in your screenshot) is accessible via standard libraries. You'd need to use platform-specific APIs to get access to the other information.
For example, assuming Windows (based on the screen shot), you'd use GetFileTime(); this function is able to retrieve the created, modified, and accessed times. You will need a handle to the file. The link above includes a link to a full example, but summarizing the example essentially you can do:
HANDLE hFile = /* get the file handle */
FILETIME ftCreate, ftAccess, ftWrite;
GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite);

Read and validate certificate from executable

I want to validate certificates of signed executable images (by validation, I mean to tell if the signature comes from MS/Adobe/Oracle etc.). Does windows provides api for this task? How should I do that, no idea. Any help would be appreciated.
I'm using Windows and C++. I want to validate native executable images, not .NET assemblies or Java jar files.
UPDATE
Ok, I'll try to describe what I want shortly.
1) Validate PE certificate. Is the signature valid or not. It should work when signature is embedded in PE and when the signature is in security catalog. (I found this on sysinternals forum and works fine, so I don't need this one anymore).
2) Tell who's the signer/publisher of the file. I know it can be achieved through CryptQueryObject (I found a working example, though it doesn't work with security catalogs), but don't know how to use it with security catalog files.
There are many API and approaches how you can get and verify the signature of the executable and how you can get other additional information which you need. The problem is which level you choose (high level like WinVerifyTrust)
The easiest first API which can be used to get cryptography context from the CAT or EXE file is CryptQueryObject function. The code example from the KB323809 could get you the main idea how to decode information what you need. the main difference if you work with CAT files is that you should modify the some parameters of CryptQueryObject. I recommend you just to use CERT_QUERY_CONTENT_FLAG_ALL and CERT_QUERY_FORMAT_FLAG_ALL and CryptQueryObject will do all what you needs internally:
BOOL bIsSuccess;
DWORD dwEncoding, dwContentType, dwFormatType;
HCERTSTORE hStore = NULL;
HCRYPTMSG hMsg = NULL;
PVOID pvContext = NULL;
// fill szFileName
...
// Get message handle and store handle from the signed file.
bIsSuccess = CryptQueryObject (CERT_QUERY_OBJECT_FILE,
szFileName,
CERT_QUERY_CONTENT_FLAG_ALL,
CERT_QUERY_FORMAT_FLAG_ALL,
0,
&dwEncoding,
&dwContentType,
&dwFormatType,
&hStore,
&hMsg,
&pvContext);
The value dwContentType set by the CryptQueryObject will get you the base information about the type of the file szFileName. The pvContext will be PCCERT_CONTEXT for the most cases which you need, but it can be also PCCRL_CONTEXT or PCCTL_CONTEXT if you use .ctl or .crl file as the input. You will receive the hStore filled with all certificates from the file szFileName. So with respect of pvContext and hStore you can examine the file contain with CryptoAPI. If you do prefer
low-level massages API you can use hMsg which will be additionally set in case of some dwContentType (at least for for CERT_QUERY_CONTENT_PKCS7_SIGNED, CERT_QUERY_CONTENT_PKCS7_UNSIGNED, CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED).
To verify the signature of the file I would recommend you to use CertGetCertificateChain and CertVerifyCertificateChainPolicy to verify not only that the certificate is valid in general, but that it (or all its parents) is valid for authenticode (szOID_PKIX_KP_CODE_SIGNING). CertGetCertificateChain can be used for different revocation scenarios. You should do two separate calls with CERT_CHAIN_POLICY_AUTHENTICODE and CERT_CHAIN_POLICY_AUTHENTICODE_TS to verify that both Authenticode chain policy and Authenticode Time Stamp chain policy are valid.
UPDATED: I reread your current question (the Updated part). Your current problem is how to get the signer/publisher of the file. So I answer only on the question.
If you use the code from sysinternal for the signature verification you should just search for the line
if ( !CryptCATCatalogInfoFromContext(CatalogContext, &InfoStruct, 0) )
The statement sill set the fields of the InfoStruct in case that that file is system windows file which signature is verified with respect of some .cat file. The field InfoStruct.wszCatalogFile will get you the name of the .cat file.
For example on my Windows 7 if I try to verify the digital signature of the C:\Windows\explorer.exe file, the .cat where its hash could be found is C:\Windows\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\Package_1_for_KB2515325~31bf3856ad364e35~amd64~~6.1.1.0.cat.
If you would use code from KB323809 with described above parameters of CryptQueryObject you will decode the SPC_SP_OPUS_INFO_OBJID ("1.3.6.1.4.1.311.2.1.12") attribute of the C:\Windows\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\Package_1_for_KB2515325~31bf3856ad364e35~amd64~~6.1.1.0.cat (see the function GetProgAndPublisherInfo) and you will know
pwszProgramName: "Windows Express Security Catalogs"
pPublisherInfo: NULL
pMoreInfo->dwLinkChoice: SPC_URL_LINK_CHOICE
pMoreInfo->pwszUrl "http://www.microsoft.com"
So no special publisher information are included for the file. If you examine the signer of the the catalog you will find out that:
The signer of the .cat file: "Microsoft Windows"
The signer signed it with the certificate:
Serial Number: 0x6115230F00000000000A
Issuer Name: Microsoft Windows Verification PCA
Full Issuer Name:
CN = Microsoft Windows Verification PCA
O = Microsoft Corporation
L = Redmond
S = Washington
C = US
Subject Name: Microsoft Windows
Full Subject Name:
CN = Microsoft Windows
OU = MOPR
O = Microsoft Corporation
L = Redmond
S = Washington
C = US
The Date of TimeStamp : 28.02.2011 21:16:36
TimeStamp Certificate:
Serial Number: 0x6103DCF600000000000C
Issuer Name: Microsoft Time-Stamp PCA
Subject Name: Microsoft Time-Stamp Service
So you should use just the signer of the .cat file, because there are no other signer of explorer.exe.
The WinVerifyTrust function performs a trust verification action on a specified object. The function passes the inquiry to a trust provider that supports the action identifier, if one exists.
For certificate verification, use the CertGetCertificateChain and CertVerifyCertificateChainPolicy functions.
#Davita
I read the above problem thoroughly and tried to solve it.
My suggestion is to try CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED instead of CERT_QUERY_CONTENT_FLAG_ALL in the third parameter of CryptQueryObject()

Edit the frame rate of an avi file

Is it possible to change the frame rate of an avi file using the Video for windows library? I tried the following steps but did not succeed.
AviFileInit
AviFileOpen(OF_READWRITE)
pavi1 = AviFileGetStream
avi_info = AviStreamInfo
avi_info.dwrate = 15
EditStreamSetInfo(dwrate) returns -2147467262.
I'm pretty sure the AVIFile* APIs don't support this. (Disclaimer: I was the one who defined those APIs, but it was over 15 years ago...)
You can't just call EditStreamSetInfo on an plain AVIStream, only one returned from CreateEditableStream.
You could use AVISave, then, but that would obviously re-copy the whole file.
So, yes, you would probably want to do this by parsing the AVI file header enough to find the one DWORD you want to change. There are lots of documents on the RIFF and AVI file formats out there, such as http://www.opennet.ru/docs/formats/avi.txt.
I don't know anything about VfW, but you could always try hex-editing the file. The framerate is probably a field somewhere in the header of the AVI file.
Otherwise, you can script some tool like mencoder[1] to copy the stream to a new file under a different framerate.
[1] http://www.mplayerhq.hu/
HRESULT: 0x80004002 (2147500034)
Name: E_NOINTERFACE
Description: The requested COM interface is not available
Severity code: Failed
Facility Code: FACILITY_NULL (0)
Error Code: 0x4002 (16386)
Does it work if you DON'T call EditStreamSetInfo?
Can you post up the code you use to set the stream info?

How to find out the distinguished name of the information store to feed to IExchangeManageStore::GetMailboxTable?

There is a Microsoft knowledge base article with sample code to open all mailboxes in a given information store. It works so far (requires a bit of copy & pasting on compilers newer than VC++ 6.0).
At one point it calls IExchangeManageStore::GetMailboxTable with the distinguished name of the information store. For the Exchange 2007 Trial Virtual Server image it has to look like this:
"/o=Litware Inc/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Configuration/cn=servers/cn=DC1".
Using OutlookSpy and clicking on IMsgStore and IExchangeManageStore reveals the desired string next to "Server DN:".
I want to avoid forcing the user to put this into a config file. So if OutlookSpy can do it, how can my application find out the distinguished name of the information store where the currently open mailbox is on?
Thinking there must be a pure MAPI solution, I believe I've figured out how OutlookSpy does it.
The following code snippet, inserted after
printf("Created MAPI session\n");
in the example from KB194627, will show the Server DN.
LPPROFSECT lpProfSect;
hr = lpSess->OpenProfileSection((LPMAPIUID)pbGlobalProfileSectionGuid, NULL, 0, &lpProfSect);
if(SUCCEEDED(hr))
{
LPSPropValue lpPropValue;
hr = HrGetOneProp(lpProfSect, PR_PROFILE_HOME_SERVER_DN, &lpPropValue);
if(SUCCEEDED(hr))
{
printf("Server DN: %s\n", lpPropValue->Value.lpszA);
MAPIFreeBuffer(lpPropValue);
}
lpProfSect->Release();
}
Update:
There is the function HrGetServerDN in the EDK 5.5 source code, it extracts the Server DN from a given session's PR_EMS_AB_HOME_MTA. I'll try it if the other way turns out to be unreliable.
It'll be in Active Directory, so you'd use ADSI/LDAP to look at CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=example,DC=com. Use Sysinternals' ADExplorer to have a dig around in there to find the value you're looking for.
I'd download the source for MFCMapi and see how they do this.