Determine the registered application for an extension - windows

I've got a file extension and I'd like to get the name of the application (if there is one) that will be invoked when I ShellExecute a file of that type. This is a WTL/C++ app. Is there any sample code out there that does this?
Thanks!

twk,
You're probably looking for the Win32 AssocQueryStringByKey Function.
http://msdn.microsoft.com/en-us/library/bb773473(VS.85).aspx
The ASSOCSTR value that specifies the type of string that is to be returned:
typedef enum {
ASSOCSTR_COMMAND = 1,
ASSOCSTR_EXECUTABLE,
ASSOCSTR_FRIENDLYDOCNAME,
ASSOCSTR_FRIENDLYAPPNAME,
ASSOCSTR_NOOPEN,
ASSOCSTR_SHELLNEWVALUE,
ASSOCSTR_DDECOMMAND,
ASSOCSTR_DDEIFEXEC,
ASSOCSTR_DDEAPPLICATION,
ASSOCSTR_DDETOPIC,
ASSOCSTR_INFOTIP,
ASSOCSTR_QUICKTIP,
ASSOCSTR_TILEINFO,
ASSOCSTR_CONTENTTYPE,
ASSOCSTR_DEFAULTICON,
ASSOCSTR_SHELLEXTENSION,
ASSOCSTR_DROPTARGET,
ASSOCSTR_DELEGATEEXECUTE,
ASSOCSTR_MAX
} ASSOCSTR;
My guess is that you want ASSOCSTR_FRIENDLYAPPNAME.

DWORD dwSize = 255;
TCHAR sBuffer[MAX_PATH] = {0};
HRESULT hr = AssocQueryString(0, ASSOCSTR_EXECUTABLE, _T(".htm"), _T("Open"), sBuffer, &dwSize);
CString csExt;
csExt.Format(_T("%s"), sBuffer);
AfxMessageBox(csExt);

Sorry, no code, but some useful information. See this related question: how-does-vista-generate-the-icon-for-documents-associated-to-my-application
It asked about icons, but it turns out the program associated to an extension is stored in the same place in the registry as the icon for that extension.

It's a Win32 FAQ since 1995 (Shell, see Google Groups, Win32)

Related

Enabling Closed-Display Mode w/o Meeting Apple's Requirements

EDIT:
I have heavily edited this question after making some significant new discoveries and the question not having any answers yet.
Historically/AFAIK, keeping your Mac awake while in closed-display mode and not meeting Apple's requirements, has only been possible with a kernel extension (kext), or a command run as root. Recently however, I have discovered that there must be another way. I could really use some help figuring out how to get this working for use in a (100% free, no IAP) sandboxed Mac App Store (MAS) compatible app.
I have confirmed that some other MAS apps are able to do this, and it looks like they might be writing YES to a key named clamshellSleepDisabled. Or perhaps there's some other trickery involved that causes the key value to be set to YES? I found the function in IOPMrootDomain.cpp:
void IOPMrootDomain::setDisableClamShellSleep( bool val )
{
if (gIOPMWorkLoop->inGate() == false) {
gIOPMWorkLoop->runAction(
OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setDisableClamShellSleep),
(OSObject *)this,
(void *)val);
return;
}
else {
DLOG("setDisableClamShellSleep(%x)\n", (uint32_t) val);
if ( clamshellSleepDisabled != val )
{
clamshellSleepDisabled = val;
// If clamshellSleepDisabled is reset to 0, reevaluate if
// system need to go to sleep due to clamshell state
if ( !clamshellSleepDisabled && clamshellClosed)
handlePowerNotification(kLocalEvalClamshellCommand);
}
}
}
I'd like to give this a try and see if that's all it takes, but I don't really have any idea about how to go about calling this function. It's certainly not a part of the IOPMrootDomain documentation, and I can't seem to find any helpful example code for functions that are in the IOPMrootDomain documentation, such as setAggressiveness or setPMAssertionLevel. Here's some evidence of what's going on behind the scenes according to Console:
I've had a tiny bit of experience working with IOMProotDomain via adapting some of ControlPlane's source for another project, but I'm at a loss for how to get started on this. Any help would be greatly appreciated. Thank you!
EDIT:
With #pmdj's contribution/answer, this has been solved!
Full example project:
https://github.com/x74353/CDMManager
This ended up being surprisingly simple/straightforward:
1. Import header:
#import <IOKit/pwr_mgt/IOPMLib.h>
2. Add this function in your implementation file:
IOReturn RootDomain_SetDisableClamShellSleep (io_connect_t root_domain_connection, bool disable)
{
uint32_t num_outputs = 0;
uint32_t input_count = 1;
uint64_t input[input_count];
input[0] = (uint64_t) { disable ? 1 : 0 };
return IOConnectCallScalarMethod(root_domain_connection, kPMSetClamshellSleepState, input, input_count, NULL, &num_outputs);
}
3. Use the following to call the above function from somewhere else in your implementation:
io_connect_t connection = IO_OBJECT_NULL;
io_service_t pmRootDomain = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPMrootDomain"));
IOServiceOpen (pmRootDomain, current_task(), 0, &connection);
// 'enable' is a bool you should assign a YES or NO value to prior to making this call
RootDomain_SetDisableClamShellSleep(connection, enable);
IOServiceClose(connection);
I have no personal experience with the PM root domain, but I do have extensive experience with IOKit, so here goes:
You want IOPMrootDomain::setDisableClamShellSleep() to be called.
A code search for sites calling setDisableClamShellSleep() quickly reveals a location in RootDomainUserClient::externalMethod(), in the file iokit/Kernel/RootDomainUserClient.cpp. This is certainly promising, as externalMethod() is what gets called in response to user space programs calling the IOConnectCall*() family of functions.
Let's dig in:
IOReturn RootDomainUserClient::externalMethod(
uint32_t selector,
IOExternalMethodArguments * arguments,
IOExternalMethodDispatch * dispatch __unused,
OSObject * target __unused,
void * reference __unused )
{
IOReturn ret = kIOReturnBadArgument;
switch (selector)
{
…
…
…
case kPMSetClamshellSleepState:
fOwner->setDisableClamShellSleep(arguments->scalarInput[0] ? true : false);
ret = kIOReturnSuccess;
break;
…
So, to invoke setDisableClamShellSleep() you'll need to:
Open a user client connection to IOPMrootDomain. This looks straightforward, because:
Upon inspection, IOPMrootDomain has an IOUserClientClass property of RootDomainUserClient, so IOServiceOpen() from user space will by default create an RootDomainUserClient instance.
IOPMrootDomain does not override the newUserClient member function, so there are no access controls there.
RootDomainUserClient::initWithTask() does not appear to place any restrictions (e.g. root user, code signing) on the connecting user space process.
So it should simply be a case of running this code in your program:
io_connect_t connection = IO_OBJECT_NULL;
IOReturn ret = IOServiceOpen(
root_domain_service,
current_task(),
0, // user client type, ignored
&connection);
Call the appropriate external method.
From the code excerpt earlier on, we know that the selector must be kPMSetClamshellSleepState.
arguments->scalarInput[0] being zero will call setDisableClamShellSleep(false), while a nonzero value will call setDisableClamShellSleep(true).
This amounts to:
IOReturn RootDomain_SetDisableClamShellSleep(io_connect_t root_domain_connection, bool disable)
{
uint32_t num_outputs = 0;
uint64_t inputs[] = { disable ? 1 : 0 };
return IOConnectCallScalarMethod(
root_domain_connection, kPMSetClamshellSleepState,
&inputs, 1, // 1 = length of array 'inputs'
NULL, &num_outputs);
}
When you're done with your io_connect_t handle, don't forget to IOServiceClose() it.
This should let you toggle clamshell sleep on or off. Note that there does not appear to be any provision for automatically resetting the value to its original state, so if your program crashes or exits without cleaning up after itself, whatever state was last set will remain. This might not be great from a user experience perspective, so perhaps try to defend against it somehow, for example in a crash handler.

How can I delete a file and send it to the recycle bin in Vista/7 using IFileOperation?

According to the documentation for IFileOperation::SetOperationFlags, the FOFX_RECYCLEONDELETE flag was introduced in Windows 8.
I would like to delete files and send them to the recycle bin. How is it possible to do that using IFileOperation in Vista and Windows 7?
I know that SHFileOperation supports that functionality, but I don't want to use SHFileOperation as Microsoft are telling us to use IFileOperation in its place. Is this possible using IFileOperation, and if so, how is it to be done?
The documentation for SetOperationFlags says:
This member can be a combination of the following flags. FOF flags are defined in Shellapi.h and FOFX flags are defined in Shobjidl.h.
So you can use the exact same flag, FOF_ALLOWUNDO, that you use with SHFileOperation to direct a delete action to move to the recycle bin.
 FOFX_RECYCLEONDELETE flag was introduced in Win 8 - will it work in Vista/7?
Since FOFX_RECYCLEONDELETE was introduced in Windows 8, then it did not exist in Vista/7, so no, it will not work in those versions.
There's always SHFileOperation but I'd rather use a more up-to-date Win32 API method. Anything else to know? Any alternate ways of recycling files/folders?
SHFileOperation() is the only documented way to recycle files/folders:
When used to delete a file, SHFileOperation permanently deletes the file unless you set the FOF_ALLOWUNDO flag in the fFlags member of the SHFILEOPSTRUCT structure pointed to by lpFileOp. Setting that flag sends the file to the Recycle Bin. If you want to simply delete a file and guarantee that it is not placed in the Recycle Bin, use DeleteFile.
That same flag is available in IFileOperation, but its documented behavior is different:
Preserve undo information, if possible.
Prior to Windows Vista, operations could be undone only from the same process that performed the original operation.
In Windows Vista and later systems, the scope of the undo is a user session. Any process running in the user session can undo another operation. The undo state is held in the Explorer.exe process, and as long as that process is running, it can coordinate the undo functions.
That is why FOFX_RECYCLEONDELETE had to be introduced - to re-add the old Recycle Bin behavior that had been lost when IFileOperation was first introduced.
I have verified David Heffernan's assessment of the FOF_ALLOWUNDO flag's use with IFileOperation to send items to the recycle bin. Here's the code. Apparently SHCreateItemFromParsingName is MS's way of saying create an item from a string. This code is catered to C++ with Qt. You'll have to initialize COM first of course.
void Worker::deleteItem(QString item)
{
HRESULT hr;
IFileOperation *pfo;
wchar_t *itemWChar = new wchar_t[item.length()+1];
item.toWCharArray(itemWChar);
itemWChar[item.length()] = 0;
PCWSTR itemPCWSTR = itemWChar;
hr = CoCreateInstance(CLSID_FileOperation,
NULL,
CLSCTX_ALL,
//IID_IFileOperation,
IID_PPV_ARGS(&pfo));
if (!SUCCEEDED(hr))
{
//error handling here
return;
}
hr = pfo->SetOperationFlags(FOF_ALLOWUNDO | FOF_NOCONFIRMATION);
if (!SUCCEEDED(hr))
{
//error handling here
return;
}
IShellItem *deleteItem = NULL;
hr = SHCreateItemFromParsingName(itemPCWSTR,
NULL,
IID_PPV_ARGS(&deleteItem));
if (!SUCCEEDED(hr))
{
//error handling here
return;
}
hr = pfo->DeleteItem(deleteItem,NULL);
if (deleteItem != NULL)
{
deleteItem->Release();
}
if (!SUCCEEDED(hr))
{
//error handling here
return;
}
hr = pfo->PerformOperations();
if (!SUCCEEDED(hr))
{
//error handling here
return;
}
pfo->Release();
delete[] itemWChar;
}

how to get serial number via win32 wpd api

as shown in title, i search on google for this question, but there seems that no way get serial number via WPD(Windows Portable Device) api, and in MSDN, i found the WPD_DEVICE_SERIAL_NUMBER property of Portable Device, can anyone tell me how to get this property using wpd api?
The C++ sample can be found here and here
Bit of a process. Basic steps are as follows:
Get and populate a IPortableDeviceValues of your client info
// Create our client information collection
ThrowIfFailed(CoCreateInstance(
CLSID_PortableDeviceValues,
nullptr,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&clientInfo)));
// We have to provide at the least our name, version, revision
ThrowIfFailed(clientInfo->SetStringValue(
WPD_CLIENT_NAME,
L"My super cool WPD client"));
ThrowIfFailed(clientInfo->SetUnsignedIntegerValue(
WPD_CLIENT_MAJOR_VERSION,
1));
ThrowIfFailed(clientInfo->SetUnsignedIntegerValue(
WPD_CLIENT_MINOR_VERSION,
0));
ThrowIfFailed(clientInfo->SetUnsignedIntegerValue(
WPD_CLIENT_REVISION,
1));
Get an IPortableDevice with CoCreateInstance
// A WPD device is represented by an IPortableDevice instance
ThrowIfFailed(CoCreateInstance(
CLSID_PortableDevice,
nullptr,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&device)));
Connect to the device using IPortableDevice::Open, passing the device's ID and the above client info
device->Open(deviceId.c_str(), clientInfo);
Get the device's IPortableDeviceContent using IPortableDevice::Content
CComPtr<IPortableDeviceContent> retVal;
ThrowIfFailedWithMessage(
device.Content(&retVal),
L"! Failed to get IPortableDeviceContent from IPortableDevice");
Get the content's IPortableDeviceProperties using IPortableDeviceContent::Properties
CComPtr<IPortableDeviceProperties> retVal;
ThrowIfFailedWithMessage(
content.Properties(&retVal),
L"! Failed to get IPortableDeviceProperties from IPortableDeviceContent");
Get the properties' IPortableDeviceValues using IPortableDeviceProperties::GetValues, passing "DEVICE" for pszObjectID and nullptr for pKeys
CComPtr<IPortableDeviceValues> retVal;
ThrowIfFailedWithMessage(
properties.GetValues(objectId.c_str(), nullptr, &retVal),
L"! Failed to get IPortableDeviceValues from IPortableDeviceProperties");
Get the serial number from the values using IPortableDeviceValues::GetStringValue, passing WPD_DEVICE_SERIAL_NUMBER for key
propertyKey = WPD_DEVICE_SERIAL_NUMBER;
LPWSTR value = nullptr;
ThrowIfFailedWithMessage(
values.GetStringValue(propertyKey, &value),
L"! Failed to get string value from IPortableDeviceValues");
propertyValue = value;
if (value != nullptr)
{
CoTaskMemFree(value);
}
By no means a complete listing, sorry. The ThrowIf* functions are just basic helpers I wrote to go from checking HRESULTs to throwing exceptions. Hopefully this points you in the right direction.
Additional references:
The dimeby8 blog
WPD Application Programming Interface

IPropertyStore_Commit method - is it needed and why isn't it implemented?

I'm trying to change the value of a flag in an IPropertyStore. However, my code seems to behave the same way, regardless of the value of the flag.
Is this because my code doesn't call IPropertyStore_Commit after changing the flag?
I did try to call the method, however I got an error code 0x80004001 which means "not implemented". Hence, the second part of my question: why isn't it implemented?
In more detail, I'm working on a Java softphone which makes use of WASAPI (via the JNI) for some of the audio processing. The native code is written in C.
Having recently enabled AES (Acoustic Echo Suppression), I've found that AGC (Automatic Gain Control) is also enabled. I'm trying to disable AGC by setting the MFPKEY_WMAAECMA_FEATR_AGC key on an IPropertyStore object. However, whatever I set the value to be makes no difference.
The relevant code snippets are as follows:
// Obtain the property store
void *pvObject;
HRESULT hr = IMediaObject_QueryInterface((IMediaObject *) thiz, &iid_, &pvObject);
// Do some checking that the store is valid...
// Set the value of the AGC key:
PROPVARIANT propvar = ...
IPropertyStore_SetValue((IPropertyStore *)pvObject, (REFPROPERTYKEY) key, &propvar);
// Call commit - fails, with 0x80004001:
HRESULT hr = IPropertyStore_Commit((IPropertyStore *)pvObject);
A couple of issues:
I'm not sure what thiz actually is; I'm pretty sure it's not an IMediaObject interface.
You can't just cast from IMediaObject to IPropertyStore; you have to QueryInterface the IMediaObject pointer for IPropertyStore.
You shouldn't need to call IPropertyStore_Commit; at least, not for setting the AGC key.
When you're calling IPropertyStore_SetValue, make sure the PROPVARIANT is initialized correctly. MFPKEY_WMAAECMA_FEATR_AGC is a BOOLEAN property, so your code needs to look something like this:
IMediaObject *pvObject;
HRESULT hr = IUnknown_QueryInterface((IUnknown*) thiz, IID_PPV_ARGS(&pvObject));
if (SUCCEEDED(hr))
{
IPropertyStore* pvPropStore;
hr = IMediaObject_QueryInterface(pvObject, IID_PPV_ARGS(&pvPropStore));
if (SUCCEEDED(hr))
{
PROPVARIANT pvFeature;
PropVariantInit(&pvFeature);
pvFeature.vt = VT_BOOL;
pvFeature.boolVal = fValue ? VBTRUE : VBFALSE;
hr = IPropertyStore_SetValue(pvPropStore, MFPKEY_WMAAECMA_FEATR_AGC, pvFeature);
}
}

Mac Sandbox: testing whether a file is accessible

Does anybody know whether there's a way of finding out whether a particular file system location is accessible under the sandbox?
I want to test whether a particular file is accessible under the normal Powerbox rules; that is has already been added to the power box using the open/ save dialog, etc.
Can I do this before triggering a sandbox exception?
Can I catch a sandbox exception?
Best regards,
Frank
You can use the OS access() system call for a quick and simple test, from man access:
#include <unistd.h>
int access(const char *path, int amode);
The access() function checks the accessibility of the file named by path
for the access permissions indicated by amode. The value of amode is the
bitwise inclusive OR of the access permissions to be checked (R_OK for
read permission, W_OK for write permission and X_OK for execute/search
permission) or the existence test, F_OK. All components of the pathname
path are checked for access permissions (including F_OK).
If path cannot be found or if any of the desired access modes would not
be granted, then a -1 value is returned and the global integer variable
errno is set to indicate the error. Otherwise, a 0 value is returned.
You could pretty this up for Objective-C using something like:
typedef enum
{
ReadAccess = R_OK,
WriteAccess = W_OK,
ExecuteAccess = X_OK,
PathExists = F_OK
} AccessKind;
BOOL isPathAccessible(NSString *path, AccessKind mode)
{
return access([path UTF8String], mode) == 0;
}
A few things. Always use fileSystemRepresentation when you need a path string. Also, R_OK is adequate if you just want to know if there is a hole in the sandbox for the specified path.
-(BOOL)isAccessibleFromSandbox:(NSString*)path
{
return( access( path.fileSystemRepresentation, R_OK) == 0 );
}

Resources