using System.Collections.Generic; using System.Runtime.InteropServices.ComTypes; using static Vanara.PInvoke.Ole32; namespace Vanara.PInvoke; /// Items from the PortableDeviceApi.dll public static partial class PortableDeviceApi { private const string Lib_PortableDeviceApi = "PortableDeviceApi.dll"; private delegate HRESULT PDMStrArrGet(string[]? arr, ref uint cnt); private delegate HRESULT PDMStrGet(string devId, StringBuilder? str, ref uint sz); /// /// The IEnumPortableDeviceObjectIDs interface enumerates the objects on a portable device. Get this interface initially by /// calling IPortableDeviceContent::EnumObjects on a device. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nn-portabledeviceapi-ienumportabledeviceobjectids [PInvokeData("portabledeviceapi.h", MSDNShortId = "NN:portabledeviceapi.IEnumPortableDeviceObjectIDs")] [ComImport, Guid("10ECE955-CF41-4728-BFA0-41EEDF1BBF19"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IEnumPortableDeviceObjectIDs : Vanara.Collections.ICOMEnum { /// The Next method retrieves the next one or more object IDs in the enumeration sequence. /// A count of the objects requested. /// /// An array of LPWSTR pointers, each specifying a retrieved object ID. The caller must allocate an array of cObjects /// LPWSTR elements. The caller must free both the array and the returned strings. The strings are freed by calling CoTaskMemFree. /// /// /// On input, this parameter is ignored. On output, the number of IDs actually retrieved. If no object IDs are released and the /// return value is S_FALSE, there are no more objects to enumerate. /// /// /// The method returns an HRESULT. Possible values include, but are not limited to, those in the following table. /// /// /// Return code /// Description /// /// /// S_OK /// The method succeeded. /// /// /// S_FALSE /// There are no more objects to enumerate. /// /// /// /// /// /// If fewer than the requested number of elements remain in the sequence, this method retrieves the remaining elements. The /// number of elements that are actually retrieved is returned through pcFetched (unless the caller passed in NULL for that /// parameter). Enumerated objects are all peers—that is, enumerating children of an object will enumerate only direct children, /// not grandchild or deeper objects. /// /// Examples /// /// /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-ienumportabledeviceobjectids-next // HRESULT Next( [in] ULONG cObjects, [in, out] LPWSTR *pObjIDs, [in, out] ULONG *pcFetched ); [PreserveSig] HRESULT Next(uint cObjects, [Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] string[] pObjIDs, out uint pcFetched); /// The Skip method skips a specified number of objects in the enumeration sequence. /// The number of objects to skip. /// /// The method returns an HRESULT. Possible values include, but are not limited to, those in the following table. /// /// /// Return code /// Description /// /// /// S_OK /// The method succeeded. /// /// /// S_FALSE /// /// The specified number of objects could not be skipped (for instance, if fewer than cObjects remained in the enumeration sequence). /// /// /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-ienumportabledeviceobjectids-skip // HRESULT Skip( [in] ULONG cObjects ); [PreserveSig] HRESULT Skip([In] uint cObjects); /// The Reset method resets the enumeration sequence to the beginning. /// /// There is no guarantee that the same objects will be enumerated after this method is called. This is because objects that /// were enumerated previously might have been deleted or new objects might have been added. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-ienumportabledeviceobjectids-reset // HRESULT Reset(); void Reset(); /// /// The Clone method duplicates the current IEnumPortableDeviceObjectIDs interface. /// Not implemented in this release. /// /// An enumeration interface. The caller must release this interface when it is finished with the interface. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-ienumportabledeviceobjectids-clone // HRESULT Clone( [out] IEnumPortableDeviceObjectIDs **ppEnum ); IEnumPortableDeviceObjectIDs Clone(); /// The Cancel method cancels a pending operation. /// /// This method cancels all pending operations on the current device handle, which corresponds to a session associated with an /// IPortableDevice interface. The Windows Portable Devices (WPD) API does not support targeted cancellation of specific operations. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-ienumportabledeviceobjectids-cancel // HRESULT Cancel(); void Cancel(); } /// /// The IPortableDevice interface provides access to a portable device. /// /// To create and open this interface, first call CoCreateInstance with CLSID_PortableDeviceFTM or /// CLSID_PortableDevice to retrieve an IPortableDevice interface, and then call Open to open a connection to the device. /// /// /// /// /// The client interfaces are designed to be used for any WPD object; it is not necessary to create a new instance for each object /// referenced by the application. After an application opens an instance of the IPortableDevice interface, it should open /// and cache any other WPD client interfaces that it will require. /// /// /// For Windows 7, IPortableDevice supports two CLSIDs for CoCreateInstance. CLSID_PortableDevice returns an /// IPortableDevice pointer that does not aggregate the free-threaded marshaler; CLSID_PortableDeviceFTM is a new /// CLSID that returns an IPortableDevice pointer that aggregates the free-threaded marshaler. Both pointers support the same /// functionality otherwise. /// /// /// Applications that live in Single Threaded Apartments should use CLSID_PortableDeviceFTM as this eliminates the overhead /// of interface pointer marshaling. CLSID_PortableDevice is still supported for legacy applications. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nn-portabledeviceapi-iportabledevice [PInvokeData("portabledeviceapi.h", MSDNShortId = "NN:portabledeviceapi.IPortableDevice")] [ComImport, Guid("625e2df8-6392-4cf0-9ad1-3cfa5f17775c"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), CoClass(typeof(PortableDevice))] public interface IPortableDevice { /// The Open method opens a connection between the application and the device. /// /// A pointer to a that contains the Plug and Play ID string for the device. You can get this string by calling IPortableDeviceManager::GetDevices. /// /// /// /// A pointer to an IPortableDeviceValues interface that holds information that identifies the application to the device. This /// interface holds PROPERTYKEY/value pairs that try to identify an application uniquely. Although the presence of a /// CoCreated interface is required, the application is not required to send any key/value pairs. However, sending data might /// improve performance. Typical key/value pairs include the application name, major and minor version, and build number. /// /// See properties beginning with "WPD_CLIENT_" in the Properties section. /// /// /// /// A device must be opened before you can call any methods on it. (Note that the IPortableDeviceManager methods do not require /// you to open a device before calling any methods.) However, usually you do not need to call Close. /// /// /// Administrators can restrict the access of portable devices to computers running on a network. For example, an administrator /// may restrict all Guest users to read-only access, while Authenticated users are given read/write access. /// /// /// Due to these security issues, if your application will not perform write operations, it should call the Open method /// and request read-only access by specifying GENERIC_READ for the WPD_CLIENT_DESIRED_ACCESS property that it supplies in the /// pClientInfo parameter. /// /// /// If your application requires write operations, it should call the Open method as shown in the following example code. /// The first time, it should request read/write access by passing the default WPD_CLIENT_DESIRED_ACCESS property in the /// pClientInfo parameter. If this first call fails and returns E_ACCESSDENIED, your application should call the Open /// method a second time and request read-only access by specifying GENERIC_READ for the WPD_CLIENT_DESIRED_ACCESS property that /// it supplies in the pClientInfo parameter. /// /// /// Applications that live in Single Threaded Apartments should use CLSID_PortableDeviceFTM, as this eliminates the /// overhead of interface pointer marshaling. CLSID_PortableDevice is still supported for legacy applications. /// /// Examples /// /// #define CLIENT_NAME L"My WPD Application" #define CLIENT_MAJOR_VER 1 #define CLIENT_MINOR_VER 0 #define CLIENT_REVISION 0 HRESULT OpenDevice(LPCWSTR wszPnPDeviceID, IPortableDevice** ppDevice) { HRESULT hr = S_OK; IPortableDeviceValues* pClientInformation = NULL; IPortableDevice* pDevice = NULL; if ((wszPnPDeviceID == NULL) || (ppDevice == NULL)) { hr = E_INVALIDARG; return hr; } // CoCreate an IPortableDeviceValues interface to hold the client information. hr = CoCreateInstance(CLSID_PortableDeviceValues, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDeviceValues, (VOID**) &pClientInformation); if (SUCCEEDED(hr)) { HRESULT ClientInfoHR = S_OK; // Attempt to set all properties for client information. If we fail to set // any of the properties below it is OK. Failing to set a property in the // client information isn't a fatal error. ClientInfoHR = pClientInformation->SetStringValue(WPD_CLIENT_NAME, CLIENT_NAME); if (FAILED(ClientInfoHR)) { // Failed to set WPD_CLIENT_NAME } ClientInfoHR = pClientInformation->SetUnsignedIntegerValue(WPD_CLIENT_MAJOR_VERSION, CLIENT_MAJOR_VER); if (FAILED(ClientInfoHR)) { // Failed to set WPD_CLIENT_MAJOR_VERSION } ClientInfoHR = pClientInformation->SetUnsignedIntegerValue(WPD_CLIENT_MINOR_VERSION, CLIENT_MINOR_VER); if (FAILED(ClientInfoHR)) { // Failed to set WPD_CLIENT_MINOR_VERSION } ClientInfoHR = pClientInformation->SetUnsignedIntegerValue(WPD_CLIENT_REVISION, CLIENT_REVISION); if (FAILED(ClientInfoHR)) { // Failed to set WPD_CLIENT_REVISION } } else { // Failed to CoCreateInstance CLSID_PortableDeviceValues for client information } ClientInfoHR = pClientInformation->SetUnsignedIntegerValue(WPD_CLIENT_SECURITY_QUALITY_OF_SERVICE, SECURITY_IMPERSONATION); if (FAILED(ClientInfoHR)) { // Failed to set WPD_CLIENT_SECURITY_QUALITY_OF_SERVICE } if (SUCCEEDED(hr)) { // CoCreate an IPortableDevice interface hr = CoCreateInstance(CLSID_PortableDeviceFTM, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDevice, (VOID**) &pDevice); if (SUCCEEDED(hr)) { // Attempt to open the device using the PnPDeviceID string given // to this function and the newly created client information. // Note that we're attempting to open the device the first // time using the default (read/write) access. If this fails // with E_ACCESSDENIED, we'll attempt to open a second time // with read-only access. hr = pDevice->Open(wszPnPDeviceID, pClientInformation); if (hr == E_ACCESSDENIED) { // Attempt to open for read-only access pClientInformation->SetUnsignedIntegerValue( WPD_CLIENT_DESIRED_ACCESS, GENERIC_READ); hr = pDevice->Open(wszPnPDeviceID, pClientInformation); } if (SUCCEEDED(hr)) { // The device successfully opened, obtain an instance of the Device into // ppDevice so the caller can be returned an opened IPortableDevice. hr = pDevice->QueryInterface(IID_IPortableDevice, (VOID**)ppDevice); if (FAILED(hr)) { // Failed to QueryInterface the opened IPortableDevice } } } else { // Failed to CoCreateInstance CLSID_PortableDevice } } // Release the IPortableDevice when finished if (pDevice != NULL) { pDevice->Release(); pDevice = NULL; } // Release the IPortableDeviceValues that contains the client information when finished if (pClientInformation != NULL) { pClientInformation->Release(); pClientInformation = NULL; } return hr; } /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevice-open HRESULT Open( // [in] LPCWSTR pszPnPDeviceID, [in] IPortableDeviceValues *pClientInfo ); void Open([In, MarshalAs(UnmanagedType.LPWStr)] string pszPnPDeviceID, [In] IPortableDeviceValues pClientInfo); /// The SendCommand method sends a command to the device and retrieves the results synchronously. /// Currently not used; specify zero. /// /// /// Pointer to an IPortableDeviceValues interface that specifies the command and parameters to call on the device. This /// interface must include the following two values to indicate the command. Additional parameters vary depending on the /// command. For a list of the parameters that are required for each command, see Commands. /// /// /// /// Command or property /// Description /// /// /// WPD_PROPERTY_COMMON_COMMAND_CATEGORY /// The category GUID of the command to send. For example, to reset a device, you would send WPD_COMMAND_COMMON_RESET_DEVICE.fmtid. /// /// /// WPD_PROPERTY_COMMON_COMMAND_ID /// The PID of the command to send. For example, to reset a device, you would send WPD_COMMAND_COMMON_RESET_DEVICE.pid. /// /// /// /// /// An IPortableDeviceValues interface that indicates the results of the command results, including success or failure, and any /// command values returned by the device. The caller must release this interface when it is done with it. The retrieved values /// vary by command; see the appropriate command documentation in Commands to learn what values are returned by each command call. /// /// /// /// This function is used to send a command directly to the driver. A command is a PROPERTYKEY that is sent to the driver /// to indicate the expected action, along with a list of required parameters. Each command has a list of required and optional /// parameters and results that must be packaged with the command for the driver to perform the requested action. A list of /// commands defined by Windows Portable Devices, with the required parameters and return values, is given in Commands. /// /// /// Most Windows Portable Devices methods actually work by sending one or more of the Windows Portable Devices commands for you /// and wrapping the parameters for you. Some commands have no corresponding Windows Portable Devices methods. The only way to /// call these commands is by using SendCommand. The following commands have no corresponding method: /// /// /// /// WPD_COMMAND_COMMON_RESET_DEVICE /// /// /// WPD_COMMAND_DEVICE_HINTS_GET_CONTENT_LOCATION /// /// /// WPD_COMMAND_SMS_SEND /// /// /// WPD_COMMAND_STILL_IMAGE_CAPTURE_INITIATE /// /// /// WPD_COMMAND_STORAGE_EJECT /// /// /// You also must call SendCommand to send any custom driver commands driver. /// /// Some custom commands may require a specific Input/Output Control Code (IOCTL) access level. Your application sets this /// access level by calling the IPortableDeviceValues::SetUnsignedIntegerValue method on the command parameters that it passes /// to the SendCommand method. For example, if a custom command requires read-only access, you would call /// SetUnsignedIntegerValue and pass WPD_API_OPTION_IOCTL_ACCESS as the first argument and FILE_READ_ACCESS as the second /// argument. By updating these command parameters, your application ensures that the Windows Portable Devices API issues the /// command with the read-only IOCTL. /// /// /// Errors that are encountered by the driver while processing a command are retrieved by the ppResults parameter, not by the /// SendCommand return value. The return value of this method is any error (or success) code that is encountered while /// sending the command to the driver. /// /// /// If a driver does not support the specified command, this method will succeed, but the only guaranteed element in the /// returned ppResults parameter will be WPD_PROPERTY_COMMON_HRESULT, which will contain E_NOTIMPL. You can verify whether a /// driver supports a command by calling IPortableDeviceCapabilities::GetSupportedCommands before calling a command. /// /// /// If a command supports options (such as delete recursively or delete nonrecursively), you can query for supported options by /// calling IPortableDeviceCapabilities::GetCommandOptions. /// /// /// There is no option to set a timeout in a call to SendCommand but the developer can attempt to cancel the command by /// calling IPortableDevice::Cancel from a separate thread. /// /// Examples /// /// // void ResetDevice(IPortableDevice* pDevice) { HRESULT hr = S_OK; CComPtr<IPortableDeviceValues> pDevValues; hr = CoCreateInstance(CLSID_PortableDeviceValues, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDeviceValues, (VOID**) &pDevValues); if (SUCCEEDED(hr)) { if (pDevValues != NULL) { hr = pDevValues->SetGuidValue(WPD_PROPERTY_COMMON_COMMAND_CATEGORY, WPD_COMMAND_COMMON_RESET_DEVICE.fmtid); if (FAILED(hr)) { printf("! IPortableDeviceValues::SetGuidValue failed, hr= 0x%lx\n", hr); } hr = pDevValues->SetUnsignedIntegerValue(WPD_PROPERTY_COMMON_COMMAND_ID, WPD_COMMAND_COMMON_RESET_DEVICE.pid); if (FAILED(hr)) { printf("! IPortableDeviceValues::SetGuidValue failed, hr= 0x%lx\n", hr); } } } hr = pDevice->SendCommand(0, pDevValues, &pDevValues); if (FAILED(hr)) { printf("! Failed to reset the device, hr = 0x%lx\n",hr); } else printf("Device successfully reset\n"); return; } // /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevice-sendcommand HRESULT // SendCommand( [in] const DWORD dwFlags, [in] IPortableDeviceValues *pParameters, [out] IPortableDeviceValues **ppResults ); IPortableDeviceValues SendCommand([Optional] uint dwFlags, [In] IPortableDeviceValues pParameters); /// The Content method retrieves an interface that you can use to access objects on a device. /// /// An IPortableDeviceContent interface that is used to access the content on a device. The caller must release this interface /// when it is done with it. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevice-content HRESULT // Content( [out] IPortableDeviceContent **ppContent ); IPortableDeviceContent Content(); /// The Capabilities method retrieves an interface used to query the capabilities of a portable device. /// /// An IPortableDeviceCapabilities interface that can describe the device's capabilities. The caller must release this interface /// when it is done with it. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevice-capabilities // HRESULT Capabilities( [out] IPortableDeviceCapabilities **ppCapabilities ); IPortableDeviceCapabilities Capabilities(); /// The Cancel method cancels a pending operation on this interface. /// /// /// If your application invokes the WPD API from multiple threads, each thread should create a new instance of the /// IPortableDevice interface. Doing this ensures that any cancel operation affects only the I/O for the affected thread. /// /// /// If an IStream write operation is underway when the Cancel method is invoked, your application should discard /// all changes by invoking the IStream::Revert method. Once the changes are discarded, the application should also close /// the stream by invoking the IUnknown::Release method. /// /// /// Also, note that if the Cancel method is invoked before an IStream::Write method has completed, the data being /// written may be corrupted. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevice-cancel HRESULT Cancel(); void Cancel(); /// The Close method closes the connection with the device. /// /// You should not usually need to call this method yourself. When the last reference to the IPortableDevice interface is /// released, Windows Portable Devices calls Close for you. Calling this method manually forces the connection to the /// device to close, and any Windows Portable Devices objects hosted on this device will cease to function. You can call Open to /// reopen the connection. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevice-close HRESULT Close(); void Close(); /// The Advise method registers an application-defined callback that receives device events. /// DWORD that specifies option flags. /// Pointer to a callback object. /// This parameter is ignored and should be set to NULL. /// /// A string that represents a unique context ID. This is used to unregister for callbacks when calling Unadvise. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevice-advise HRESULT // Advise( [in] const DWORD dwFlags, [in] IPortableDeviceEventCallback *pCallback, [in] IPortableDeviceValues *pParameters, // [out] LPWSTR *ppszCookie ); void Advise([Optional] uint dwFlags, IPortableDeviceEventCallback pCallback, [Optional] IPortableDeviceValues? pParameters, [MarshalAs(UnmanagedType.LPWStr)] out string ppszCookie); /// /// The Unadvise method unregisters a client from receiving callback notifications. You must call this method if you /// called Advise previously. /// /// A unique context ID. This was retrieved in the initial call to IPortableDevice::Advise. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevice-unadvise HRESULT // Unadvise( [in] LPCWSTR pszCookie ); void Unadvise([In, MarshalAs(UnmanagedType.LPWStr)] string pszCookie); /// /// The GetPnPDeviceID method retrieves the Plug and Play (PnP) device identifier that the application used to open the device. /// /// The Plug and Play ID string for the device. /// /// /// After the application is through using the string returned by this method, it must call the CoTaskMemFree function to free /// the string. /// /// The ppszPnPDeviceID argument must not be set to NULL. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevice-getpnpdeviceid // HRESULT GetPnPDeviceID( [out] LPWSTR *ppszPnPDeviceID ); [return: MarshalAs(UnmanagedType.LPWStr)] string GetPnPDeviceID(); } /// /// The IPortableDeviceCapabilities interface a variety of device capabilities, including supported formats, commands, and /// functional objects. You can retrieve this interface from a device by calling IPortableDevice::Capabilities. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nn-portabledeviceapi-iportabledevicecapabilities [PInvokeData("portabledeviceapi.h", MSDNShortId = "NN:portabledeviceapi.IPortableDeviceCapabilities")] [ComImport, Guid("2C8C6DBF-E3DC-4061-BECC-8542E810D126"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPortableDeviceCapabilities { /// The GetSupportedCommands method retrieves a list of all the supported commands for this device. /// /// An IPortableDeviceKeyCollection interface that holds all the valid commands. For a list of commands that are defined by /// Windows Portable Devices, see Commands. The caller must release this interface when it is done with it. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecapabilities-getsupportedcommands // HRESULT GetSupportedCommands( [out] IPortableDeviceKeyCollection **ppCommands ); IPortableDeviceKeyCollection GetSupportedCommands(); /// The GetCommandOptions method retrieves all the supported options for the specified command on the device. /// /// A REFPROPERTYKEY that specifies a command to query for supported options. For a list of the commands that are defined /// by Windows Portable Devices, see Commands. /// /// /// An IPortableDeviceValues interface that contains the supported options. If no options are supported, this will not contain /// any values. The caller must release this interface when it is done with it. For more information, see Remarks. /// /// /// /// This method is called by applications that want to call a command directly on the driver by calling /// IPortableDevice::SendCommand. Some commands allow the caller to specify additional options. For example, some drivers /// support recursive child deletion when deleting an object using the WPD_COMMAND_OBJECT_MANAGEMENT_DELETE_OBJECTS command. /// /// /// If an option is a simple Boolean value, the key of the retrieved IPortableDeviceValues interface will be the name of the /// option, and the PROPVARIANT value will be a VT_BOOL value of True or False. If an option has several values, the /// retrieved PROPVARIANT value will be a collection type that holds the supported values. /// /// /// If this method is called for the WPD_COMMAND_STORAGE_FORMAT command and the ppOptions parameter is set to /// WPD_OPTION_VALID_OBJECT_IDS, the driver will return an IPortableDevicePropVariant collection of type VT_LPWSTR that /// specifies the identifiers for each object on the device that can be formatted. (If this option does not exist, the format /// command is available for all objects.) /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecapabilities-getcommandoptions // HRESULT GetCommandOptions( [in] REFPROPERTYKEY Command, [out] IPortableDeviceValues **ppOptions ); IPortableDeviceValues GetCommandOptions(in PROPERTYKEY Command); /// The GetFunctionalCategories method retrieves all functional categories supported by the device. /// /// An IPortableDevicePropVariantCollection interface that holds all the functional categories for this device. The values will /// be GUID s of type VT_CLSID in the retrieved PROPVARIANT values. The caller must release this interface when it /// is done with it. /// /// /// /// Functional categories describe the types of functions that a device can perform, such as image capture, audio capture, and /// storage. This method is typically very fast, because the driver usually queries the device only on startup and caches the results. /// /// Examples /// For an example of how to use this method see Retrieving the Functional Categories Supported by a Device. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecapabilities-getfunctionalcategories // HRESULT GetFunctionalCategories( [out] IPortableDevicePropVariantCollection **ppCategories ); IPortableDevicePropVariantCollection GetFunctionalCategories(); /// The GetFunctionalObjects method retrieves all functional objects that match a specified category on the device. /// /// A REFGUID that specifies the category to search for. This can be WPD_FUNCTIONAL_CATEGORY_ALL to return all functional objects. /// /// /// An IPortableDevicePropVariantCollection interface that contains the object IDs of the functional objects as strings (type /// VT_LPWSTR in the retrieved PROPVARIANT items). If no objects of the requested type are found, this will be an empty /// collection (not NULL). The caller must release this interface when it is done with it. /// /// /// /// This operation is usually fast, because the driver does not need to perform a full content enumeration, and the number of /// retrieved functional objects is typically less than 10. If no objects of the requested type are found, this method will not /// return an error, but returns an empty collection for ppObjectIDs. /// /// Examples /// For an example of how to use this method, see Retrieving the Functional Object Identifiers for a Device /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecapabilities-getfunctionalobjects // HRESULT GetFunctionalObjects( [in] REFGUID Category, [out] IPortableDevicePropVariantCollection **ppObjectIDs ); IPortableDevicePropVariantCollection GetFunctionalObjects(in Guid Category); /// /// The GetSupportedContentTypes method retrieves all supported content types for a specified functional object type on a device. /// /// /// A REFGUID that specifies a functional object category. To get a list of functional categories on the device, call IPortableDeviceCapabilities::GetFunctionalCategories. /// /// /// An IPortableDevicePropVariantCollection interface that lists all the supported object types for the specified functional /// object category. These object types will be GUID values of type VT_CLSID in the retrieved PROPVARIANT items. /// See Requirements for Objects for a list of object types defined by Windows Portable Devices. The caller must release this /// interface when it is done with it. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecapabilities-getsupportedcontenttypes // HRESULT GetSupportedContentTypes( [in] REFGUID Category, [out] IPortableDevicePropVariantCollection **ppContentTypes ); IPortableDevicePropVariantCollection GetSupportedContentTypes(in Guid Category); /// /// The GetSupportedFormats method retrieves the supported formats for a specified object type on the device. For /// example, specifying audio objects might return WPD_OBJECT_FORMAT_WMA, WPD_OBJECT_FORMAT_WAV, and WPD_OBJECT_FORMAT_MP3. /// /// /// A REFGUID that specifies a content type, such as image, audio, or video. For a list of content types that are defined /// by Windows Portable Devices, see Requirements for Objects. /// /// /// An IPortableDevicePropVariantCollection interface that lists the supported formats for the specified content type. These are /// GUID values (type VT_CLSID) in the retrieved collection items. For a list of formats that are supported by Windows Portable /// Devices, see Object Formats. The caller must release this interface when it is done with it. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecapabilities-getsupportedformats // HRESULT GetSupportedFormats( [in] REFGUID ContentType, [out] IPortableDevicePropVariantCollection **ppFormats ); IPortableDevicePropVariantCollection GetSupportedFormats(in Guid ContentType); /// /// The GetSupportedFormatProperties method retrieves the properties supported by objects of a specified format on the device. /// /// /// A REFGUID that specifies the format of the object. For a list of formats that are defined by Windows Portable /// Devices, see Object Formats. /// /// /// An IPortableDeviceKeyCollection interface that contains the supported properties for the specified format. For a list of /// properties defined by Windows Portable Devices, see Properties and Attributes. The caller must release this interface when /// it is done with it. /// /// /// You can specify WPD_OBJECT_FORMAT_ALL for the Format parameter to retrieve the complete set of property attributes. /// /// If an object does not have a value assigned to a specific property, or if the property was deleted, a device might not /// report the property at all when enumerating its properties. Another device might report the property, but with an empty /// string or a value of zero. In order to avoid this inconsistency, you can call this method to learn all the properties you /// can set on a specific object. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecapabilities-getsupportedformatproperties // HRESULT GetSupportedFormatProperties( [in] REFGUID Format, [out] IPortableDeviceKeyCollection **ppKeys ); IPortableDeviceKeyCollection GetSupportedFormatProperties(in Guid Format); /// /// The GetFixedPropertyAttributes method retrieves the standard property attributes for a specified property and format. /// Standard attributes are those that have the same value for all objects of the same format. For example, one device might not /// allow users to modify video file names; this device would return WPD_PROPERTY_ATTRIBUTE_CAN_WRITE with a value of /// False for WMV formatted objects. Attributes that can have different values for a format, or optional attributes, are not returned. /// /// /// A REFGUID that specifies the format of the objects of interest. For format GUID values, see Object Formats. /// /// /// A REFPROPERTYKEY that specifies the property that you want to know the attributes of. Properties defined by Windows /// Portable Devices are listed in Properties and Attributes. /// /// /// An IPortableDeviceValues interface that holds the attributes and their values. The caller must release this interface when /// it is done with it. /// /// /// You can specify WPD_OBJECT_FORMAT_ALL for the Format parameter to retrieve the complete set of property attributes. /// /// Attributes describe properties. Example attributes are WPD_PROPERTY_ATTRIBUTE_CAN_READ and /// WPD_PROPERTY_ATTRIBUTE_CAN_WRITE. This method does not retrieve resource attributes. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecapabilities-getfixedpropertyattributes // HRESULT GetFixedPropertyAttributes( [in] REFGUID Format, [in] REFPROPERTYKEY Key, [out] IPortableDeviceValues **ppAttributes ); IPortableDeviceValues? GetFixedPropertyAttributes(in Guid Format, in PROPERTYKEY Key); /// The Cancel method cancels a pending request on this interface. /// /// This method cancels all pending operations on the current device handle, which corresponds to a session associated with an /// IPortableDevice interface. The Windows Portable Devices (WPD) API does not support targeted cancellation of specific operations. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecapabilities-cancel // HRESULT Cancel(); void Cancel(); /// The GetSupportedEvents method retrieves the supported events for this device. /// /// An IPortableDevicePropVariantCollection interface that lists the supported events. The caller must release this interface /// when it is done with it. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecapabilities-getsupportedevents // HRESULT GetSupportedEvents( [out] IPortableDevicePropVariantCollection **ppEvents ); IPortableDevicePropVariantCollection GetSupportedEvents(); /// The GetEventOptions method retrieves all the supported options for the specified event on the device. /// /// A REFGUID that specifies a event to query for supported options. For a list of the events that are defined by Windows /// Portable Devices, see Events. /// /// /// An IPortableDeviceValues interface that contains the supported options. If no options are supported, this will not contain /// any values. The caller must release this interface when it is done with it. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecapabilities-geteventoptions // HRESULT GetEventOptions( [in] REFGUID Event, [out] IPortableDeviceValues **ppOptions ); IPortableDeviceValues GetEventOptions(in Guid Event); } /// /// The IPortableDeviceContent interface provides methods to create, enumerate, examine, and delete content on a device. To /// get this interface, call IPortableDevice::Content. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nn-portabledeviceapi-iportabledevicecontent [PInvokeData("portabledeviceapi.h", MSDNShortId = "NN:portabledeviceapi.IPortableDeviceContent")] [ComImport, Guid("6A96ED84-7C73-4480-9938-BF5AF477D426"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPortableDeviceContent { /// /// The EnumObjects method retrieves an interface that is used to enumerate the immediate child objects of an object. It /// has an optional filter that can enumerate objects with specific properties. /// /// Currently ignored; specify zero. /// /// The ID of the parent. This can be an empty string (but not a NULL /// pointer) or the defined constant WPD_DEVICE_OBJECT_ID to indicate the device root. /// /// This parameter is ignored and should be set to NULL. /// /// An IEnumPortableDeviceObjectIDs interface that is used to enumerate the objects that are found. The caller must release this /// interface when it is done with it. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-enumobjects // HRESULT EnumObjects( [in] const DWORD dwFlags, [in] LPCWSTR pszParentObjectID, [in] IPortableDeviceValues *pFilter, [out] // IEnumPortableDeviceObjectIDs **ppEnum ); IEnumPortableDeviceObjectIDs EnumObjects([Optional] uint dwFlags, [In, MarshalAs(UnmanagedType.LPWStr)] string pszParentObjectID, [In, Optional] IPortableDeviceValues? pFilter); /// /// The Properties method retrieves the interface that is required to get or set properties on an object on the device. /// /// /// An IPortableDeviceProperties interface that is used to get or set object properties. The caller must release this interface /// when it is done with it. /// /// /// /// The retrieved interface is not specific to a particular object on the device; it is specific only to the device. You must /// specify the ID of the object you want when requesting or setting properties. /// /// Examples /// For an example of how to use this method, see Setting Properties for a Single Object. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-properties // HRESULT Properties( [out] IPortableDeviceProperties **ppProperties ); IPortableDeviceProperties Properties(); /// /// The Transfer method retrieves an interface that is used to read from or write to the content data of an existing object resource. /// /// /// An IPortableDeviceResources interface that is used to modify an object's resources. The caller must release this interface /// when it is done with it. /// /// /// This method is typically used to read from an existing object. /// Examples /// For an example of how to use this method, see Adding a Resource to an Object. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-transfer // HRESULT Transfer( [out] IPortableDeviceResources **ppResources ); IPortableDeviceResources Transfer(); /// The CreateObjectWithPropertiesOnly method creates an object with only properties on the device. /// /// An IPortableDeviceValues collection of properties to assign to the object. For a list of required and optional properties /// for an object, see Requirements for Objects. /// /// /// An optional string to receive the name of the new object. Can be NULL, if not needed. Windows Portable Devices /// defines the constant WPD_DEVICE_OBJECT_ID to represent a device. The SDK allocates this memory; the caller must release it /// using CoTaskMemFree. /// /// /// /// Some objects are only a collection of properties—such as a folder, which is only a collection of pointers to other /// objects—while other objects are both properties and data—such as an audio file, which contains all the properties and the /// actual music bits. This method is used to create an object that contains only properties. To create an object with both /// properties and data, use CreateObjectWithPropertiesAndData. /// /// This method is synchronous; when it returns, the new object should be present on the device. /// /// The object that the driver actually creates might be a properties-and-data object, depending on what type of object is most /// convenient for the driver. To check what kind of object the driver has created, request the WPD_OBJECT_FORMAT property of /// the new object. /// /// The object will be created on the device when this method returns. /// Examples /// For an example of how to use this method, see Transferring a Properties-Only Object to the Device. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-createobjectwithpropertiesonly // HRESULT CreateObjectWithPropertiesOnly( IPortableDeviceValues *pValues, [in, out] LPWSTR *ppszObjectID ); [return: MarshalAs(UnmanagedType.LPWStr)] string CreateObjectWithPropertiesOnly(IPortableDeviceValues pValues); /// The CreateObjectWithPropertiesAndData method creates an object with both properties and data on the device. /// /// An IPortableDeviceValues collection of properties to assign to the object. For a list of required and optional /// properties for an object, see Requirements for Objects. /// /// /// An IStream interface that the application uses to send the object data to the device. The object will not be created /// on the device until the application sends the data by calling ppData-> Commit. To abandon a data transfer in /// progress, you can call ppData -> Revert. The caller must release this interface when it is done with it. The /// underlying object extends both IStream and IPortableDeviceDataStream. /// /// /// An optional DWORD pointer that specifies the optimal buffer size for the application to use when writing the data to /// ppData. The application can specify TRUE to ignore this. /// /// /// An optional unique, ID that is used to identify this creation request in the application's implementation of /// IPortableDeviceEventCallback (if implemented). When the device finishes creating the object, it will send this identifier to /// the callback function. This identifier allows an application to monitor object creation in a different thread from the one /// that called CreateObjectWithPropertiesOnly. The SDK allocates this memory, and the caller must release it using CoTaskMemFree. /// /// /// /// Some objects are only a collection of properties—such as a folder, which is only a collection of pointers to other /// objects—while other objects are both properties and data—such as an audio file, which contains all the properties and the /// actual music bits. This method is used to create an object that requires both properties and data. To create a /// properties-only object, call CreateObjectWithPropertiesOnly. /// /// /// Because the object is not created until the application calls Commit on the retrieved IStream ppData, the /// object will not have an ID until Commit is called on it. Commit is synchronous, so when that method returns /// successfully, the object will exist on the device. /// /// /// After calling Commit to create the object, call QueryInterface on ppData for IPortableDeviceDataStream, and /// then call IPortableDeviceDataStream::GetObjectID to get the ID of the newly created object. /// /// Examples /// For an example of how to use this method, see Transferring an Image or Music File to the Device. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-createobjectwithpropertiesanddata // HRESULT CreateObjectWithPropertiesAndData( IPortableDeviceValues *pValues, [out] IStream **ppData, [in, out] DWORD // *pdwOptimalWriteBufferSize, [in, out] LPWSTR *ppszCookie ); [return: MarshalAs(UnmanagedType.LPWStr)] string CreateObjectWithPropertiesAndData(IPortableDeviceValues pValues, out IStream ppData, [In, Out] ref uint pdwOptimalWriteBufferSize); /// The Delete method deletes one or more objects from the device. /// One of the DELETE_OBJECT_OPTIONS enumerators. /// /// Pointer to an IPortableDevicePropVariantCollection interface that holds one or more null-terminated strings (type VT_LPWSTR) /// specifying the object IDs of the objects to delete. /// /// /// Optional. On return, this parameter contains a collection of VT_ERROR values indicating the success or failure of the /// operation. The first element returned in ppResults corresponds to the first object in the pObjectIDs collection, the second /// element returned in ppResults corresponds to the second object in the pObjectIDs collection, and so on. This parameter can /// be NULL if the application is not concerned with the results. /// /// /// /// To see if recursive deletion is supported, call IPortableDeviceCapabilities::GetCommandOptions. If the retrieved /// IPortableDeviceValues interface contains a property value called WPD_OPTION_OBJECT_MANAGEMENT_RECURSIVE_DELETE_SUPPORTED /// with a boolVal value of True, the device supports recursive deletion. /// /// The following table lists the possible return codes that may appear in the collection at which ppResults points. /// Examples /// For an example of how to use this method, see Deleting Content from the Device. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-delete // HRESULT Delete( [in] const DWORD dwOptions, [in] IPortableDevicePropVariantCollection *pObjectIDs, [in, out] // IPortableDevicePropVariantCollection **ppResults ); IPortableDevicePropVariantCollection Delete(DELETE_OBJECT_OPTIONS dwOptions, IPortableDevicePropVariantCollection pObjectIDs); /// /// The GetObjectIDsFromPersistentUniqueIDs method retrieves the current object ID of one or more objects, given their /// persistent unique IDs (PUIDs). /// /// /// Pointer to an IPortableDevicePropVariantCollection interface that contains one or more persistent unique ID (PUID) string /// values (type VT_LPWSTR). /// /// /// Pointer to an IPortableDevicePropVariantCollection interface pointer that contains the retrieved object IDs, as type /// VT_LPWSTR. The retrieved IDs will be in the same order as the submitted PUIDs; if a value could not be found, it is /// indicated by an empty string. The caller must release this interface when it is done with it. /// /// /// /// Windows Portable Devices Object IDs are unique across the device, but may be different across sessions. An Object ID can /// change when the application reconnects to the device. /// /// /// Certain applications, such as synchronization engines, require a way to identify the object across connection sessions. /// Every object has a WPD_OBJECT_PERSISTENT_UNIQUE_ID property, which indicates an identifier that is persistent across /// sessions. Applications can read and save this property in their initial session, by calling the Properties method. /// /// Examples /// For an example of how to use this method, see Retrieving an Object Identifier from a Persistent Unique Identifier /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-getobjectidsfrompersistentuniqueids // HRESULT GetObjectIDsFromPersistentUniqueIDs( [in] IPortableDevicePropVariantCollection *pPersistentUniqueIDs, [out] // IPortableDevicePropVariantCollection **ppObjectIDs ); IPortableDevicePropVariantCollection GetObjectIDsFromPersistentUniqueIDs(IPortableDevicePropVariantCollection pPersistentUniqueIDs); /// The Cancel method cancels a pending operation called on this interface. /// /// This method cancels all pending operations on the current device handle, which corresponds to a session associated with an /// IPortableDevice interface. The Windows Portable Devices (WPD) API does not support targeted cancellation of specific operations. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-cancel // HRESULT Cancel(); void Cancel(); /// The Move method moves one or more objects from one location on the device to another. /// /// Pointer to an IPortableDevicePropVariantCollection interface that holds one or more null-terminated strings (type VT_LPWSTR) /// specifying the object IDs of the objects to be moved. /// /// The ID of the destination. /// /// Optional. On return, this parameter contains a collection of VT_ERROR values indicating the success or failure of the /// operation. The first element returned in ppResults corresponds to the first object in the pObjectIDs collection, the second /// element returned in ppResults corresponds to the second object in the pObjectIDs collection, and so on. This parameter can /// be NULL if the application is not concerned with the results. /// /// /// /// If the specified device supports move operations on a functional storage, the pszDestinationFolderObjectID parameter may /// specify the identifier for a functional storage. /// /// Examples /// For an example of how to use this method, see Moving Content on the Device. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-move HRESULT // Move( [in] IPortableDevicePropVariantCollection *pObjectIDs, [in] LPCWSTR pszDestinationFolderObjectID, [in, out] // IPortableDevicePropVariantCollection **ppResults ); IPortableDevicePropVariantCollection Move(IPortableDevicePropVariantCollection pObjectIDs, [MarshalAs(UnmanagedType.LPWStr)] string pszDestinationFolderObjectID); /// The Copy method copies objects from one location on a device to another. /// A collection of object identifiers for the objects that this method will copy. /// /// An object identifier for the destination folder (or functional storage) into which this method will copy the specified objects. /// /// /// A collection of VT_ERROR values indicating the success or failure of copying a particular element. The first error value /// corresponds to the first object in the collection of object identifiers, the second to the second element, and so on. This /// argument can be NULL. /// /// /// If the specified device supports copy operations to a functional storage, the pszDestinationFolderObjectID parameter may /// specify the identifier for a functional storage. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-copy HRESULT // Copy( IPortableDevicePropVariantCollection *pObjectIDs, LPCWSTR pszDestinationFolderObjectID, [out] // IPortableDevicePropVariantCollection **ppResults ); IPortableDevicePropVariantCollection Copy(IPortableDevicePropVariantCollection pObjectIDs, [MarshalAs(UnmanagedType.LPWStr)] string pszDestinationFolderObjectID); } /// /// The IPortableDeviceContent2 interface defines additional methods that provide access to content found on a device. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nn-portabledeviceapi-iportabledevicecontent2 [PInvokeData("portabledeviceapi.h", MSDNShortId = "NN:portabledeviceapi.IPortableDeviceContent2")] [ComImport, Guid("9B4ADD96-F6BF-4034-8708-ECA72BF10554"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPortableDeviceContent2 : IPortableDeviceContent { /// /// The EnumObjects method retrieves an interface that is used to enumerate the immediate child objects of an object. It /// has an optional filter that can enumerate objects with specific properties. /// /// Currently ignored; specify zero. /// /// The ID of the parent. This can be an empty string (but not a NULL /// pointer) or the defined constant WPD_DEVICE_OBJECT_ID to indicate the device root. /// /// This parameter is ignored and should be set to NULL. /// /// An IEnumPortableDeviceObjectIDs interface that is used to enumerate the objects that are found. The caller must release this /// interface when it is done with it. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-enumobjects // HRESULT EnumObjects( [in] const DWORD dwFlags, [in] LPCWSTR pszParentObjectID, [in] IPortableDeviceValues *pFilter, [out] // IEnumPortableDeviceObjectIDs **ppEnum ); new IEnumPortableDeviceObjectIDs EnumObjects([Optional] uint dwFlags, [In, MarshalAs(UnmanagedType.LPWStr)] string pszParentObjectID, [In, Optional] IPortableDeviceValues? pFilter); /// /// The Properties method retrieves the interface that is required to get or set properties on an object on the device. /// /// /// An IPortableDeviceProperties interface that is used to get or set object properties. The caller must release this interface /// when it is done with it. /// /// /// /// The retrieved interface is not specific to a particular object on the device; it is specific only to the device. You must /// specify the ID of the object you want when requesting or setting properties. /// /// Examples /// For an example of how to use this method, see Setting Properties for a Single Object. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-properties // HRESULT Properties( [out] IPortableDeviceProperties **ppProperties ); new IPortableDeviceProperties Properties(); /// /// The Transfer method retrieves an interface that is used to read from or write to the content data of an existing object resource. /// /// /// An IPortableDeviceResources interface that is used to modify an object's resources. The caller must release this interface /// when it is done with it. /// /// /// This method is typically used to read from an existing object. /// Examples /// For an example of how to use this method, see Adding a Resource to an Object. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-transfer // HRESULT Transfer( [out] IPortableDeviceResources **ppResources ); new IPortableDeviceResources Transfer(); /// The CreateObjectWithPropertiesOnly method creates an object with only properties on the device. /// /// An IPortableDeviceValues collection of properties to assign to the object. For a list of required and optional properties /// for an object, see Requirements for Objects. /// /// /// An optional string to receive the name of the new object. Can be NULL, if not needed. Windows Portable Devices /// defines the constant WPD_DEVICE_OBJECT_ID to represent a device. The SDK allocates this memory; the caller must release it /// using CoTaskMemFree. /// /// /// /// Some objects are only a collection of properties—such as a folder, which is only a collection of pointers to other /// objects—while other objects are both properties and data—such as an audio file, which contains all the properties and the /// actual music bits. This method is used to create an object that contains only properties. To create an object with both /// properties and data, use CreateObjectWithPropertiesAndData. /// /// This method is synchronous; when it returns, the new object should be present on the device. /// /// The object that the driver actually creates might be a properties-and-data object, depending on what type of object is most /// convenient for the driver. To check what kind of object the driver has created, request the WPD_OBJECT_FORMAT property of /// the new object. /// /// The object will be created on the device when this method returns. /// Examples /// For an example of how to use this method, see Transferring a Properties-Only Object to the Device. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-createobjectwithpropertiesonly // HRESULT CreateObjectWithPropertiesOnly( IPortableDeviceValues *pValues, [in, out] LPWSTR *ppszObjectID ); [return: MarshalAs(UnmanagedType.LPWStr)] new string CreateObjectWithPropertiesOnly(IPortableDeviceValues pValues); /// The CreateObjectWithPropertiesAndData method creates an object with both properties and data on the device. /// /// An IPortableDeviceValues collection of properties to assign to the object. For a list of required and optional /// properties for an object, see Requirements for Objects. /// /// /// An IStream interface that the application uses to send the object data to the device. The object will not be created /// on the device until the application sends the data by calling ppData-> Commit. To abandon a data transfer in /// progress, you can call ppData -> Revert. The caller must release this interface when it is done with it. The /// underlying object extends both IStream and IPortableDeviceDataStream. /// /// /// An optional DWORD pointer that specifies the optimal buffer size for the application to use when writing the data to /// ppData. The application can specify TRUE to ignore this. /// /// /// An optional unique, ID that is used to identify this creation request in the application's implementation of /// IPortableDeviceEventCallback (if implemented). When the device finishes creating the object, it will send this identifier to /// the callback function. This identifier allows an application to monitor object creation in a different thread from the one /// that called CreateObjectWithPropertiesOnly. The SDK allocates this memory, and the caller must release it using CoTaskMemFree. /// /// /// /// Some objects are only a collection of properties—such as a folder, which is only a collection of pointers to other /// objects—while other objects are both properties and data—such as an audio file, which contains all the properties and the /// actual music bits. This method is used to create an object that requires both properties and data. To create a /// properties-only object, call CreateObjectWithPropertiesOnly. /// /// /// Because the object is not created until the application calls Commit on the retrieved IStream ppData, the /// object will not have an ID until Commit is called on it. Commit is synchronous, so when that method returns /// successfully, the object will exist on the device. /// /// /// After calling Commit to create the object, call QueryInterface on ppData for IPortableDeviceDataStream, and /// then call IPortableDeviceDataStream::GetObjectID to get the ID of the newly created object. /// /// Examples /// For an example of how to use this method, see Transferring an Image or Music File to the Device. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-createobjectwithpropertiesanddata // HRESULT CreateObjectWithPropertiesAndData( IPortableDeviceValues *pValues, [out] IStream **ppData, [in, out] DWORD // *pdwOptimalWriteBufferSize, [in, out] LPWSTR *ppszCookie ); [return: MarshalAs(UnmanagedType.LPWStr)] new string CreateObjectWithPropertiesAndData(IPortableDeviceValues pValues, out IStream ppData, [In, Out] ref uint pdwOptimalWriteBufferSize); /// The Delete method deletes one or more objects from the device. /// One of the DELETE_OBJECT_OPTIONS enumerators. /// /// Pointer to an IPortableDevicePropVariantCollection interface that holds one or more null-terminated strings (type VT_LPWSTR) /// specifying the object IDs of the objects to delete. /// /// /// Optional. On return, this parameter contains a collection of VT_ERROR values indicating the success or failure of the /// operation. The first element returned in ppResults corresponds to the first object in the pObjectIDs collection, the second /// element returned in ppResults corresponds to the second object in the pObjectIDs collection, and so on. This parameter can /// be NULL if the application is not concerned with the results. /// /// /// /// To see if recursive deletion is supported, call IPortableDeviceCapabilities::GetCommandOptions. If the retrieved /// IPortableDeviceValues interface contains a property value called WPD_OPTION_OBJECT_MANAGEMENT_RECURSIVE_DELETE_SUPPORTED /// with a boolVal value of True, the device supports recursive deletion. /// /// The following table lists the possible return codes that may appear in the collection at which ppResults points. /// Examples /// For an example of how to use this method, see Deleting Content from the Device. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-delete // HRESULT Delete( [in] const DWORD dwOptions, [in] IPortableDevicePropVariantCollection *pObjectIDs, [in, out] // IPortableDevicePropVariantCollection **ppResults ); new IPortableDevicePropVariantCollection Delete(DELETE_OBJECT_OPTIONS dwOptions, IPortableDevicePropVariantCollection pObjectIDs); /// /// The GetObjectIDsFromPersistentUniqueIDs method retrieves the current object ID of one or more objects, given their /// persistent unique IDs (PUIDs). /// /// /// Pointer to an IPortableDevicePropVariantCollection interface that contains one or more persistent unique ID (PUID) string /// values (type VT_LPWSTR). /// /// /// Pointer to an IPortableDevicePropVariantCollection interface pointer that contains the retrieved object IDs, as type /// VT_LPWSTR. The retrieved IDs will be in the same order as the submitted PUIDs; if a value could not be found, it is /// indicated by an empty string. The caller must release this interface when it is done with it. /// /// /// /// Windows Portable Devices Object IDs are unique across the device, but may be different across sessions. An Object ID can /// change when the application reconnects to the device. /// /// /// Certain applications, such as synchronization engines, require a way to identify the object across connection sessions. /// Every object has a WPD_OBJECT_PERSISTENT_UNIQUE_ID property, which indicates an identifier that is persistent across /// sessions. Applications can read and save this property in their initial session, by calling the Properties method. /// /// Examples /// For an example of how to use this method, see Retrieving an Object Identifier from a Persistent Unique Identifier /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-getobjectidsfrompersistentuniqueids // HRESULT GetObjectIDsFromPersistentUniqueIDs( [in] IPortableDevicePropVariantCollection *pPersistentUniqueIDs, [out] // IPortableDevicePropVariantCollection **ppObjectIDs ); new IPortableDevicePropVariantCollection GetObjectIDsFromPersistentUniqueIDs(IPortableDevicePropVariantCollection pPersistentUniqueIDs); /// The Cancel method cancels a pending operation called on this interface. /// /// This method cancels all pending operations on the current device handle, which corresponds to a session associated with an /// IPortableDevice interface. The Windows Portable Devices (WPD) API does not support targeted cancellation of specific operations. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-cancel // HRESULT Cancel(); new void Cancel(); /// The Move method moves one or more objects from one location on the device to another. /// /// Pointer to an IPortableDevicePropVariantCollection interface that holds one or more null-terminated strings (type VT_LPWSTR) /// specifying the object IDs of the objects to be moved. /// /// The ID of the destination. /// /// Optional. On return, this parameter contains a collection of VT_ERROR values indicating the success or failure of the /// operation. The first element returned in ppResults corresponds to the first object in the pObjectIDs collection, the second /// element returned in ppResults corresponds to the second object in the pObjectIDs collection, and so on. This parameter can /// be NULL if the application is not concerned with the results. /// /// /// /// If the specified device supports move operations on a functional storage, the pszDestinationFolderObjectID parameter may /// specify the identifier for a functional storage. /// /// Examples /// For an example of how to use this method, see Moving Content on the Device. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-move HRESULT // Move( [in] IPortableDevicePropVariantCollection *pObjectIDs, [in] LPCWSTR pszDestinationFolderObjectID, [in, out] // IPortableDevicePropVariantCollection **ppResults ); new IPortableDevicePropVariantCollection Move(IPortableDevicePropVariantCollection pObjectIDs, [MarshalAs(UnmanagedType.LPWStr)] string pszDestinationFolderObjectID); /// The Copy method copies objects from one location on a device to another. /// A collection of object identifiers for the objects that this method will copy. /// /// An object identifier for the destination folder (or functional storage) into which this method will copy the specified objects. /// /// /// A collection of VT_ERROR values indicating the success or failure of copying a particular element. The first error value /// corresponds to the first object in the collection of object identifiers, the second to the second element, and so on. This /// argument can be NULL. /// /// /// If the specified device supports copy operations to a functional storage, the pszDestinationFolderObjectID parameter may /// specify the identifier for a functional storage. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent-copy HRESULT // Copy( IPortableDevicePropVariantCollection *pObjectIDs, LPCWSTR pszDestinationFolderObjectID, [out] // IPortableDevicePropVariantCollection **ppResults ); new IPortableDevicePropVariantCollection Copy(IPortableDevicePropVariantCollection pObjectIDs, [MarshalAs(UnmanagedType.LPWStr)] string pszDestinationFolderObjectID); /// /// The UpdateObjectWithPropertiesAndData method updates an object by using properties and data found on the device. /// /// The identifier of the object to update. /// The IPortableDeviceValues interface that specifies the object properties to be updated. /// The IStream interface through which the object data is sent to the device. /// /// The optimal buffer size for writing the object data to ppData, or NULL if the buffer size is ignored. /// /// /// /// Device formats and object formats can derive some of their object properties from the data itself. Or, they can have /// property values that depend on the data. For example, a music track has a duration property that is specified when an /// application calls the IPortableDeviceContent::CreateObjectWithPropertiesAndData method. If this track is stored as a default /// resource (WPD_RESOURCE_DEFAULT), the application might update it. The application additionally mighthave to update the /// duration property. This method lets the application perform both updates at the same time. /// /// An update is incomplete until the IStream::Commit method is called on the object referenced by the ppData parameter. /// /// To abandon a data transfer in progress, an application should call the IStream::Revert method on the object /// referenced by the ppData parameter. /// /// /// The IStream interface object referenced by the ppData parameter must be released after the update operation is /// complete, or, is canceled. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecontent2-updateobjectwithpropertiesanddata // HRESULT UpdateObjectWithPropertiesAndData( [in] LPCWSTR pszObjectID, [in] IPortableDeviceValues *pProperties, [out] IStream // **ppData, [in, out] DWORD *pdwOptimalWriteBufferSize ); void UpdateObjectWithPropertiesAndData([MarshalAs(UnmanagedType.LPWStr)] string pszObjectID, IPortableDeviceValues pProperties, out IStream ppData, out uint pdwOptimalWriteBufferSize); } /// /// The IPortableDeviceDataStream interface exposes additional methods on an IStream that is used for data transfers. /// It is obtained by calling QueryInterface on the IStream that is retrieved by IPortableDeviceResources::GetStream /// or IPortableDeviceContent::CreateObjectWithPropertiesAndData. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nn-portabledeviceapi-iportabledevicedatastream [PInvokeData("portabledeviceapi.h", MSDNShortId = "NN:portabledeviceapi.IPortableDeviceDataStream")] [ComImport, Guid("88e04db3-1012-4d64-9996-f703a950d3f4"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPortableDeviceDataStream : IStream { /// new void Read(byte[] pv, int cb, IntPtr pcbRead); /// new void Write(byte[] pv, int cb, IntPtr pcbWritten); /// new void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition); /// new void SetSize(long libNewSize); /// new void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten); /// new void Commit(int grfCommitFlags); /// new void Revert(); /// new void LockRegion(long libOffset, long cb, int dwLockType); /// new void UnlockRegion(long libOffset, long cb, int dwLockType); /// new void Stat(out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, int grfStatFlag); /// new void Clone(out IStream ppstm); /// /// The GetObjectID method retrieves the object ID of the resource that was written to the device. This method is only /// valid after calling IStream::Commit on the data stream. /// /// The ID of the object just transferred to the device. /// /// An object ID is created after the object is created on the device. Therefore, a new object that is created by calling /// IPortableDeviceContent::CreateObjectWithPropertiesAndData will not have an ID assigned until the application calls /// Commit on the data transfer stream. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicedatastream-getobjectid // HRESULT GetObjectID( [out] LPWSTR *ppszObjectID ); [return: MarshalAs(UnmanagedType.LPWStr)] string GetObjectID(); /// The Cancel method cancels a call in progress on this interface. /// /// This method cancels all pending operations on the current device handle, which corresponds to a session associated with an /// IPortableDevice interface. The Windows Portable Devices (WPD) API does not support targeted cancellation of specific operations. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicedatastream-cancel // HRESULT Cancel(); void Cancel(); } /// Represents a factory that can instantiate a WPD Automation Device object. /// /// /// The IPortableDeviceDispatchFactory interface can be CoCreated directly using CLSID_PortableDeviceDispatchFactory /// as in the following code. /// /// /// /// /// Examples /// /// For an example of how to use the IPortableDeviceDispatchFactory interface to instantiate a WPD Automation Device /// object, see Instantiating the WPD Automation Factory Interface. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nn-portabledeviceapi-iportabledevicedispatchfactory [PInvokeData("portabledeviceapi.h", MSDNShortId = "NN:portabledeviceapi.IPortableDeviceDispatchFactory")] [ComImport, Guid("5e1eafc3-e3d7-4132-96fa-759c0f9d1e0f"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), CoClass(typeof(PortableDeviceDispatchFactory))] public interface IPortableDeviceDispatchFactory { /// Instantiates a WPD Automation Device object for a given WPD device identifier. /// /// A pointer to a String that is used by Plug-and-play to identify a currently connected WPD device. The Plug and Play /// (PnP) identifier for a particular device can be obtained from the IPortableDeviceManager::GetDevices method in the WPD /// C++/COM API. /// /// Contains a pointer to the IDispatch implementation for the WPD Automation Device object. /// /// For an example of how to use GetDeviceDispatch method to instantiate a WPD Automation Device object, see /// Instantiating the WPD Automation Factory Interface. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicedispatchfactory-getdevicedispatch // HRESULT GetDeviceDispatch( [in] LPCWSTR pszPnPDeviceID, [out] IDispatch **ppDeviceDispatch ); [return: MarshalAs(UnmanagedType.IDispatch)] object GetDeviceDispatch([MarshalAs(UnmanagedType.LPWStr)] string pszPnPDeviceID); } /// /// The IPortableDeviceEventCallback interface implemented by the application to receive asynchronous callbacks if an /// application has registered to receive them by calling IPortableDevice::Advise. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nn-portabledeviceapi-iportabledeviceeventcallback [PInvokeData("portabledeviceapi.h", MSDNShortId = "NN:portabledeviceapi.IPortableDeviceEventCallback")] [ComImport, Guid("A8792A31-F385-493C-A893-40F64EB45F6E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPortableDeviceEventCallback { /// The OnEvent method is called by the SDK to notify the application about asynchronous events. /// Pointer to an IPortableDeviceValues interface that contains event details. /// Any values returned by the application are ignored by Windows Portable Devices. /// /// The application must register to receive events by calling IPortableDevice::Advise. /// Examples /// For an example of how to use this method, see Handling Events from the Device. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceeventcallback-onevent // HRESULT OnEvent( [in] IPortableDeviceValues *pEventParameters ); void OnEvent([Optional] IPortableDeviceValues? pEventParameters); } /// /// /// Enumerates devices that are connected to the computer and provides a simple way to request installation information, including /// manufacturer, friendly name, and description. This is typically the first Windows Portable Devices interface created by an /// application. To create an instance of this interface, call CoCreateInstance and specify CLSID_PortableDeviceManager. /// /// /// The properties that are requested using this interface can also be requested by using the IPortableDeviceProperties interface. /// However, that interface requires several steps to acquire; using this interface is a much simpler way to request device information. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nn-portabledeviceapi-iportabledevicemanager [PInvokeData("portabledeviceapi.h", MSDNShortId = "NN:portabledeviceapi.IPortableDeviceManager")] [ComImport, Guid("a1567595-4c2f-4574-a6fa-ecef917b9a40"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), CoClass(typeof(PortableDeviceManager))] public interface IPortableDeviceManager { /// Retrieves a list of portable devices connected to the computer. /// /// A caller-allocated array of strings that holds the Plug and Play names of all of the connected devices. To learn the /// required size for this parameter, first call this method with this parameter set to NULL and pcPnPDeviceIDs set to /// zero, and then allocate a buffer according to the value retrieved by pcPnPDeviceIDs. These names can be used by /// IPortableDevice::Open to create a connection to a device. /// /// /// On input, the number of values that pPnPDeviceIDs can hold. On output, a pointer to the number of devices actually written /// to pPnPDeviceIDs. /// /// /// /// The list of devices is generated when the device manager is instantiated; it does not refresh as devices connect and /// disconnect. To refresh the list of connected devices, call RefreshDeviceList. /// /// /// The API allocates the memory for each string pointed to by the pPnPDeviceIDs array. Once your application no longer needs /// these strings, it must iterate through this array and free the associated memory by calling the CoTaskMemFree function. /// /// Examples /// /// For an example of how to use this method to enumerate devices, see Enumerating Devices. For an example of how to use this /// method to enumerate Services, see Enumerating Services. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicemanager-getdevices // HRESULT GetDevices( [in, out] LPWSTR *pPnPDeviceIDs, [in, out] DWORD *pcPnPDeviceIDs ); [PreserveSig] HRESULT GetDevices([In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1)] string[]? pPnPDeviceIDs, ref uint pcPnPDeviceIDs); /// The RefreshDeviceList method refreshes the list of devices that are connected to the computer. /// /// /// When the IPortableDeviceManager interface is instantiated the first time, it generates a list of the devices that are /// connected. However, devices can connect and disconnect from the computer, making the original list obsolete. This method /// enables an application to refresh the list of connected devices. /// /// /// This method is less resource-intensive than instantiating a new device manager to generate a new device list. However, it /// does require some resources; therefore, we recommend that you do not call this method arbitrarily. The best solution is to /// have the application register to get device arrival and removal notifications, and when a notification is received, have the /// application call this function. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicemanager-refreshdevicelist // HRESULT RefreshDeviceList(); void RefreshDeviceList(); /// Retrieves the user-friendly name for the device. /// /// The device's Plug and Play ID. You can retrieve a list of Plug and Play names of all devices that are connected to the /// computer by calling GetDevices. /// /// /// A caller-allocated buffer that is used to hold the user-friendly name for the device. To learn the required size for this /// parameter, first call this method with this parameter set to NULL and pcchDeviceFriendlyName set to 0; the /// method will succeed and set pcchDeviceFriendlyName to the required buffer size to hold the device-friendly name, including /// the termination character. /// /// /// On input, the maximum number of characters that pDeviceFriendlyName can hold, not including the termination character. On /// output, the number of characters that is returned by pDeviceFriendlyName, not including the termination character. /// /// /// A device is not required to support this method. If this method fails to retrieve a name, try requesting the WPD_OBJECT_NAME /// property of the device object (the object with the ID WPD_DEVICE_OBJECT_ID). /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicemanager-getdevicefriendlyname // HRESULT GetDeviceFriendlyName( [in] LPCWSTR pszPnPDeviceID, [in, out] WCHAR *pDeviceFriendlyName, [in, out] DWORD // *pcchDeviceFriendlyName ); [PreserveSig] HRESULT GetDeviceFriendlyName([In, MarshalAs(UnmanagedType.LPWStr)] string pszPnPDeviceID, [In, Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder? pDeviceFriendlyName, [In, Out] ref uint pcchDeviceFriendlyName); /// Retrieves the description of a device. /// /// The device's Plug and Play ID. You can retrieve a list of Plug and Play names of devices that are currently connected by /// calling GetDevices. /// /// /// A caller-allocated buffer to hold the user-description name of the device. The caller must allocate the memory for this /// parameter. To learn the required size for this parameter, first call this method with this parameter set to NULL and /// pcchDeviceDescription set to 0; the method will succeed and set pcchDeviceDescription to the required buffer size to /// hold the device-friendly name, including the termination character. /// /// /// The number of characters (not including the termination character) in pDeviceDescription. On input, the maximum length of /// pDeviceDescription; on output, the length of the returned string in pDeviceDescription. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicemanager-getdevicedescription // HRESULT GetDeviceDescription( [in] LPCWSTR pszPnPDeviceID, [in, out] WCHAR *pDeviceDescription, [in, out] DWORD // *pcchDeviceDescription ); [PreserveSig] HRESULT GetDeviceDescription([In, MarshalAs(UnmanagedType.LPWStr)] string pszPnPDeviceID, [In, Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder? pDeviceDescription, [In, Out] ref uint pcchDeviceDescription); /// Retrieves the name of the device manufacturer. /// /// The device's Plug and Play ID. You can retrieve a list of Plug and Play names of all devices that are connected to the /// computer by calling GetDevices. /// /// /// A caller-allocated buffer that holds the name of the device manufacturer. To learn the required size for this parameter, /// first call this method with this parameter set to NULL and pcchDeviceManufacturer set to 0; the method will /// succeed and set pcchDeviceManufacturer to the required buffer size to hold the device-friendly name, including the /// termination character. /// /// /// On input, the maximum number of characters that pDeviceManufacturer can hold, not including the termination character. On /// output, the number of characters returned by pDeviceManufacturer, not including the termination character. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicemanager-getdevicemanufacturer // HRESULT GetDeviceManufacturer( [in] LPCWSTR pszPnPDeviceID, [in, out] WCHAR *pDeviceManufacturer, [in, out] DWORD // *pcchDeviceManufacturer ); [PreserveSig] HRESULT GetDeviceManufacturer([In, MarshalAs(UnmanagedType.LPWStr)] string pszPnPDeviceID, [In, Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder? pDeviceManufacturer, [In, Out] ref uint pcchDeviceManufacturer); /// /// Retrieves a property value stored by the device on the computer. (These are not standard properties that are defined by /// Windows Portable Devices.) /// /// /// The device's Plug and Play ID. You can retrieve a list of Plug and Play names of all devices that are connected to the /// computer by calling GetDevices. /// /// /// The name of the property to request. These are custom property names defined by a device manufacturer. /// /// /// A caller-allocated buffer to hold the retrieved data. To get the size required, call this method with this parameter set to /// NULL and pcbData set to zero, and the required size will be retrieved in pcbData. This call will also return an error /// that can be ignored. See Return Values. /// /// The size of the buffer allocated or returned by pData, in bytes. /// /// A constant describing the type of data returned in pData. The values for this parameter are the same types used to describe /// the lpType parameter of the Platform SDK function RegQueryValueEx. /// /// /// /// These property values are stored on device installation, or stored by a device during operation so that they can be /// persisted across connection sessions. An application must know the exact name of the property, which is specified by the /// device itself; therefore, this method is intended to be used by device developers who are creating their own applications. /// /// /// To get Windows Portable Devices properties from the device object, call IPortableDeviceProperties::GetValues, and specify /// the device object with WPD_DEVICE_OBJECT_ID. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicemanager-getdeviceproperty // HRESULT GetDeviceProperty( [in] LPCWSTR pszPnPDeviceID, [in] LPCWSTR pszDevicePropertyName, [in, out] BYTE *pData, [in, out] // DWORD *pcbData, [in, out] DWORD *pdwType ); [PreserveSig] HRESULT GetDeviceProperty([MarshalAs(UnmanagedType.LPWStr)] string pszPnPDeviceID, [MarshalAs(UnmanagedType.LPWStr)] string pszDevicePropertyName, [In, Out] IntPtr pData, ref uint pcbData, out REG_VALUE_TYPE pdwType); /// /// The GetPrivateDevices method retrieves a list of private portable devices connected to the computer. These private /// devices are only accessible through an application that is designed for these particular devices. /// /// /// A caller-allocated array of strings that holds the Plug and Play names of all of the connected devices. To learn the /// required size for this parameter, first call this method with this parameter set to NULL and pcPnPDeviceIDs set to /// zero, and then allocate a buffer according to the value retrieved by pcPnPDeviceIDs. These names can be used by /// IPortableDevice::Open to create a connection to a device. /// /// /// On input, the number of values that pPnPDeviceIDs can hold. On output, a pointer to the number of devices actually written /// to pPnPDeviceIDs. /// /// /// /// In order to write an application that communicates with a private device, you must have knowledge of the custom /// functionality exposed by a particular device driver. The description of this functionality must be obtained from the device manufacturer. /// /// /// The list of devices is generated when the device manager is instantiated; it does not refresh as devices connect and /// disconnect. To refresh the list of connected devices, call RefreshDeviceList. /// /// /// The API allocates the memory for each string pointed to by the pPnPDeviceIDs array. Once your application no longer needs /// these strings, it must iterate through this array and free the associated memory by calling the CoTaskMemFree function. /// /// /// A private device may not respond correctly to the standard Windows Portable Devices function calls that perform object /// enumeration, resource transfer, retrieval of device capabilities, and so on. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicemanager-getprivatedevices // HRESULT GetPrivateDevices( [in, out] LPWSTR *pPnPDeviceIDs, [in, out] DWORD *pcPnPDeviceIDs ); [PreserveSig] HRESULT GetPrivateDevices([In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1)] string[]? pPnPDeviceIDs, ref uint pcPnPDeviceIDs); } /// /// The IPortableDeviceProperties interface retrieves, adds, or deletes properties from an object on a device, or the device /// itself. To get this interface, call IPortableDeviceContent::Properties on an object. To get this interface for the object, /// specify WPD_DEVICE_OBJECT_ID in GetValues. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nn-portabledeviceapi-iportabledeviceproperties [PInvokeData("portabledeviceapi.h", MSDNShortId = "NN:portabledeviceapi.IPortableDeviceProperties")] [ComImport, Guid("7F6D695C-03DF-4439-A809-59266BEEE3A6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPortableDeviceProperties { /// /// The GetSupportedProperties method retrieves a list of properties that a specified object supports. Note that not all /// of these properties may actually have values. /// /// The object ID of the object to query. To specify the device, use WPD_DEVICE_OBJECT_ID. /// /// An IPortableDeviceKeyCollection interface that contains the supported properties. For a list of properties defined by /// Windows Portable Devices, see Properties and Attributes. The caller must release this interface when it is done with it. /// /// To get the values of supported properties, call GetPropertyAttributes. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceproperties-getsupportedproperties // HRESULT GetSupportedProperties( [in] LPCWSTR pszObjectID, [out] IPortableDeviceKeyCollection **ppKeys ); IPortableDeviceKeyCollection GetSupportedProperties([MarshalAs(UnmanagedType.LPWStr)] string pszObjectID); /// The GetPropertyAttributes method retrieves attributes of a specified object property on a device. /// The object ID of the object to query. To specify the device, use WPD_DEVICE_OBJECT_ID. /// /// A REFPROPERTYKEY that specifies the property to query for. You can retrieve a list of supported properties by calling /// GetSupportedProperties. For a list of properties that are defined by Windows Portable Devices, see Properties and Attributes. /// /// /// An IPortableDeviceValues interface that holds the retrieved property attributes. These are PROPERTYKEY/value pairs, where /// the PROPERTYKEY is the property, and the value data type depends on the specific property. The caller must release /// this interface when it is done with it. Attributes defined by Windows Portable Devices can be found on the Properties and /// Attributes page. /// /// /// /// Property attributes describe a property's access rights, valid values, and other information. For example, a property can /// have a WPD_PROPERTY_ATTRIBUTE_CAN_DELETE value set to False to prevent deletion, and have a range of valid values stored as /// individual entries. /// /// Examples /// For an example of how to use this method, see Setting Properties for a Single Object. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceproperties-getpropertyattributes // HRESULT GetPropertyAttributes( [in] LPCWSTR pszObjectID, [in] REFPROPERTYKEY Key, [out] IPortableDeviceValues **ppAttributes ); IPortableDeviceValues GetPropertyAttributes([MarshalAs(UnmanagedType.LPWStr)] string pszObjectID, in PROPERTYKEY Key); /// The GetValues method retrieves a list of specified properties from a specified object on a device. /// The ID of the object to query. To specify the device, use WPD_DEVICE_OBJECT_ID. /// /// Pointer to an IPortableDeviceKeyCollection interface that contains one or more properties to query for. If this is /// NULL, all properties will be retrieved. See Properties and Attributes for a list of properties that are defined by /// Windows Portable Devices. /// /// /// An IPortableDeviceValues interface that contains the requested property values. These will be returned as PROPERTYKEY/value /// pairs, where the data type of the value depends on the property. If a value could not be retrieved for some reason, the /// returned type will be VT_ERROR, and contain an HRESULT value describing the retrieval error. The caller must release this /// interface when it is done with it. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceproperties-getvalues // HRESULT GetValues( [in] LPCWSTR pszObjectID, [in] IPortableDeviceKeyCollection *pKeys, [out] IPortableDeviceValues **ppValues ); IPortableDeviceValues GetValues([MarshalAs(UnmanagedType.LPWStr)] string pszObjectID, IPortableDeviceKeyCollection? pKeys); /// The SetValues method adds or modifies one or more properties on a specified object on a device. /// The object ID of the object to modify. To specify the device, use WPD_DEVICE_OBJECT_ID. /// /// Pointer to an IPortableDeviceValues interface that contains one or more property/value pairs to set. Existing values will be overwritten. /// /// /// An IPortableDeviceValues interface that contains a collection of property/HRESULT values. Each value (type VT_ERROR) /// describes the success or failure of the property set attempt. The caller must release this interface when it is done with it. /// /// /// /// To delete a property, call IPortableDeviceProperties::Delete. A property can be deleted only if its /// WPD_PROPERTY_ATTRIBUTE_CAN_WRITE attribute is True. This attribute can be retrieved by calling GetPropertyAttributes. /// /// Examples /// For an example of how to use this method, see Setting Properties for a Single Object. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceproperties-setvalues // HRESULT SetValues( [in] LPCWSTR pszObjectID, [in] IPortableDeviceValues *pValues, [out] IPortableDeviceValues **ppResults ); IPortableDeviceValues SetValues([MarshalAs(UnmanagedType.LPWStr)] string pszObjectID, IPortableDeviceValues pValues); /// The Delete method deletes specified properties from a specified object on a device. /// The ID of the object whose properties you will delete. To specify the device, use WPD_DEVICE_OBJECT_ID. /// /// Pointer to an IPortableDeviceKeyCollection interface that specifies which properties to delete. For a list of properties /// defined by Windows Portable Devices, see Properties and Attributes. /// /// /// /// Properties can be deleted only if their WPD_PROPERTY_ATTRIBUTE_CAN_DELETE attribute is True. This attribute can be retrieved /// by calling GetPropertyAttributes. /// /// /// The driver has no way to indicate partial success; that is, if only some properties could be deleted, the driver will return /// S_FALSE, but this method does not indicate which properties were successfully deleted. The only way to learn which /// properties were deleted is to request all properties by calling IPortableDeviceProperties::GetValues. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceproperties-delete // HRESULT Delete( [in] LPCWSTR pszObjectID, [in] IPortableDeviceKeyCollection *pKeys ); void Delete([MarshalAs(UnmanagedType.LPWStr)] string pszObjectID, IPortableDeviceKeyCollection pKeys); /// The Cancel method cancels a pending call. /// /// This method cancels all pending operations on the current device handle, which corresponds to a session associated with an /// IPortableDevice interface. The Windows Portable Devices (WPD) API does not support targeted cancellation of specific operations. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceproperties-cancel // HRESULT Cancel(); void Cancel(); } /// /// /// The IPortableDevicePropertiesBulk interface queries or sets multiple properties on multiple objects on a device, /// asynchronously. Information is returned by an application-implemented IPortableDevicePropertiesBulkCallback interface. /// /// /// To get this interface, call QueryInterface on IPortableDeviceProperties. If the device does not support bulk /// operations, this call will fail with E_NOINTERFACE. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nn-portabledeviceapi-iportabledevicepropertiesbulk [PInvokeData("portabledeviceapi.h", MSDNShortId = "NN:portabledeviceapi.IPortableDevicePropertiesBulk")] [ComImport, Guid("482b05c0-4056-44ed-9e0f-5e23b009da93"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPortableDevicePropertiesBulk { /// /// The QueueGetValuesByObjectList method queues a request for one or more specified properties from one or more /// specified objects on the device. /// /// /// Pointer to an IPortableDevicePropVariantCollection interface that lists the object IDs of all the objects to query. These /// will be of type VT_LPWSTR. /// /// /// Pointer to an IPortableDeviceKeyCollection interface that specifies the properties to request. For a list of properties /// defined by Windows Portable Devices, see Properties and Attributes. Specify NULL to indicate all properties from the /// specified objects. /// /// /// Pointer to an application-implemented IPortableDevicePropertiesBulkCallback interface that will receive the information as /// it is retrieved. /// /// /// Pointer to a GUID that is used to start, cancel, or identify the request IPortableDevicePropertiesBulkCallback /// callbacks, if implemented. /// /// /// /// The queued request is not started until the application calls Start. For more information on how to use this method, see /// IPortableDevicePropertiesBulk Interface. /// /// /// Due to performance issues, some devices may not return a comprehensive list of properties when the pKeys parameter is NULL. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicepropertiesbulk-queuegetvaluesbyobjectlist // HRESULT QueueGetValuesByObjectList( [in] IPortableDevicePropVariantCollection *pObjectIDs, [in] IPortableDeviceKeyCollection // *pKeys, [in] IPortableDevicePropertiesBulkCallback *pCallback, [out] GUID *pContext ); void QueueGetValuesByObjectList(IPortableDevicePropVariantCollection pObjectIDs, [Optional] IPortableDeviceKeyCollection? pKeys, IPortableDevicePropertiesBulkCallback pCallback, out Guid pContext); /// /// The QueueGetValuesByObjectFormat interface queues a request for properties of objects of a specific format on a device. /// /// /// Pointer to a GUID that specifies the object format. Only objects of this type are queried. /// /// /// The object ID of the parent object where the search should begin. To search all the objects on a device, specify WPD_DEVICE_OBJECT_ID. /// /// /// The maximum depth to search below the parent, where 1 means immediate children only. It is acceptable for this number to be /// greater than the actual number of levels. To search to any depth, specify 0xFFFFFFFF /// /// /// Pointer to an IPortableDeviceKeyCollection interface that contains the properties to retrieve. For a list of /// properties that are defined by Windows Portable Devices, see Properties and Attributes. Specify NULL to indicate all /// properties from the specified format. /// /// /// Pointer to an application-implemented IPortableDevicePropertiesBulkCallback interface that will receive the information as /// it is retrieved. /// /// /// Pointer to a GUID that will be used to start, cancel, or identify the request in /// IPortableDevicePropertiesBulkCallback callbacks, if implemented. /// /// /// /// If you specify WPD_OBJECT_FORMAT_ALL for the pguidObjectFormat parameter, this method will return properties for all objects /// on the device. /// /// /// If the pszParentObjectID parameter is set to an empty string (""), the method will perform a search that is dependent on the /// dwDepth parameter as described in the following table. /// /// /// /// dwDepth /// Method returns /// /// /// 0 /// No results /// /// /// 1 /// Values for the specified device only. /// /// /// 2 /// Values for the specified device and all functional objects found on that device. /// /// /// /// If the pszParentObjectID parameter is set to WPD_DEVICE_OBJECT_ID, the method will perform a search that is dependent on the /// dwDepth parameter as described in the following table. /// /// /// /// dwDepth /// Method returns /// /// /// 0 /// Values for the specified device only. /// /// /// 1 /// Values for the specified device and all functional objects found on that device. /// /// /// /// The queued request is not started until the application calls Start. For more information on how to use this method, see /// IPortableDevicePropertiesBulk Interface. /// /// /// Due to performance issues, some devices may not return a comprehensive list of properties when the pKeys parameter is NULL. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicepropertiesbulk-queuegetvaluesbyobjectformat // HRESULT QueueGetValuesByObjectFormat( [in] REFGUID pguidObjectFormat, [in] LPCWSTR pszParentObjectID, [in] const DWORD // dwDepth, [in] IPortableDeviceKeyCollection *pKeys, [in] IPortableDevicePropertiesBulkCallback *pCallback, [out] GUID // *pContext ); void QueueGetValuesByObjectFormat(in Guid pguidObjectFormat, [MarshalAs(UnmanagedType.LPWStr)] string pszParentObjectID, uint dwDepth, [Optional] IPortableDeviceKeyCollection? pKeys, IPortableDevicePropertiesBulkCallback pCallback, out Guid pContext); /// /// The QueueSetValuesByObjectList method queues a request to set one or more specified values on one or more specified /// objects on the device. /// /// /// Pointer to an IPortableDeviceValuesCollection interface that contains the properties and values to set on specified objects. /// This interface holds one or more IPortableDeviceValues interfaces, each representing a single object. Each /// IPortableDeviceValues interface holds a collection of key/value pairs, where the key is the PROPERTYKEY /// identifying the property, and the value is a data type that varies by property. Each IPortableDeviceValues interface /// also holds one WPD_OBJECT_ID property that identifies the object to which this interface refers. /// /// /// Pointer to an application-implemented IPortableDevicePropertiesBulkCallback interface that will receive the information as /// it is retrieved. /// /// /// Pointer to a GUID that is used to start, cancel, or identify the request to any client-implemented /// IPortableDevicePropertiesBulkCallback callbacks. /// /// /// The queued request is not started until the application calls Start. For more information on how to use this method, see /// IPortableDevicePropertiesBulk Interface. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicepropertiesbulk-queuesetvaluesbyobjectlist // HRESULT QueueSetValuesByObjectList( [in] IPortableDeviceValuesCollection *pObjectValues, [in] // IPortableDevicePropertiesBulkCallback *pCallback, [out] GUID *pContext ); void QueueSetValuesByObjectList(IPortableDeviceValuesCollection pObjectValues, IPortableDevicePropertiesBulkCallback pCallback, out Guid pContext); /// The Start method starts a queued operation. /// /// A pointer to a GUID that identifies the operation to start. This value is generated by a Queue... method of this interface. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicepropertiesbulk-start // HRESULT Start( [in] REFGUID pContext ); void Start(in Guid pContext); /// The Cancel method cancels a pending properties request. /// /// Pointer to a context GUID that was retrieved when an asynchronous request was started by calling one of the Queue... methods. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicepropertiesbulk-cancel // HRESULT Cancel( [in] REFGUID pContext ); void Cancel(in Guid pContext); } /// /// /// The IPortableDevicePropertiesBulkCallback interface is implemented by the application to track the progress of an /// asynchronous operation that was begun by using the IPortableDevicePropertiesBulk interface. /// /// /// After the application calls IPortableDevicePropertiesBulk::Start, Windows Portable Devices calls /// IPortableDevicePropertiesBulkCallback::OnStart first, and then repeatedly calls /// IPortableDevicePropertiesBulkCallback::OnProgress with information until the operation is completed or the application /// calls IPortableDevicePropertiesBulk::Cancel or returns an error value for OnProgress. Finally, regardless of whether the /// operation completed successfully, Windows Portable Devices calls IPortableDevicePropertiesBulkCallback::OnEnd. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nn-portabledeviceapi-iportabledevicepropertiesbulkcallback [PInvokeData("portabledeviceapi.h", MSDNShortId = "NN:portabledeviceapi.IPortableDevicePropertiesBulkCallback")] [ComImport, Guid("9deacb80-11e8-40e3-a9f3-f557986a7845"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPortableDevicePropertiesBulkCallback { /// /// The OnStart method is called by the SDK when a bulk operation started by IPortableDevicePropertiesBulk::Start is /// about to begin. /// /// /// Pointer to a GUID that identifies which operation has started. This value is produced by a Queue... method of the /// IPortableDevicePropertiesBulk interface. /// /// /// The application should return either S_OK or an error code to abandon the operation. The application should handle all error /// codes in the same manner. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicepropertiesbulkcallback-onstart // HRESULT OnStart( [in] REFGUID pContext ); [PreserveSig] HRESULT OnStart(in Guid pContext); /// /// The OnProgress method is called by the SDK when a bulk operation started by IPortableDevicePropertiesBulk::Start has /// sent data to the device and received some information back. /// /// /// Pointer to a GUID that identifies which operation is in progress. This value is produced by a Queue... method of the /// IPortableDevicePropertiesBulk interface. /// /// /// Pointer to an IPortableDeviceValuesCollection interface that contains the results retrieved from the device. This interface /// will hold one or more IPortableDeviceValues interfaces. Each of these interfaces will hold one WPD_OBJECT_ID property with a /// string value (VT_LPSTR) specifying the object ID of the object that these values pertain to. The rest of the values in each /// IPortableDeviceValues interface vary, depending on the bulk operation being reported. For the /// QueueGetValuesByObjectFormat and QueueGetValuesByObjectList methods, they will be retrieved values of varying /// types. For QueueSetValuesByObjectList, they will be VT_ERRORHRESULT values for any errors encountered when /// setting values. /// /// /// The application should return either S_OK, or an error code to abandon the operation. All error codes are handled the same way. /// /// /// This method can be called once or multiple times, depending on how large the operation is. /// /// This method does not necessarily retrieve all properties at once, nor does it return the properties in a particular order. /// /// If this method is called multiple times, it may return properties for the same object identifier each time. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicepropertiesbulkcallback-onprogress // HRESULT OnProgress( [in] REFGUID pContext, [in] IPortableDeviceValuesCollection *pResults ); [PreserveSig] HRESULT OnProgress(in Guid pContext, IPortableDeviceValuesCollection pResults); /// /// The OnEnd method is called by the SDK when a bulk operation that is started by IPortableDevicePropertiesBulk::Start /// is completed. /// /// /// Pointer to a GUID that identifies which operation has finished. This value is produced by a Queue... method of the /// IPortableDevicePropertiesBulk interface. /// /// Contains any errors returned by the driver after the bulk operation has completed. /// The method's return value is ignored. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicepropertiesbulkcallback-onend // HRESULT OnEnd( [in] REFGUID pContext, [out] HRESULT hrStatus ); void OnEnd(in Guid pContext, HRESULT hrStatus); } /// /// The IPortableDeviceResources interface provides access to an object's raw data. Use this interface to read or write /// resources in an object. To get this interface, call IPortableDeviceContent::Transfer. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nn-portabledeviceapi-iportabledeviceresources [PInvokeData("portabledeviceapi.h", MSDNShortId = "NN:portabledeviceapi.IPortableDeviceResources")] [ComImport, Guid("FD8878AC-D841-4D17-891C-E6829CDB6934"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPortableDeviceResources { /// The GetSupportedResources method retrieves a list of resources that are supported by a specific object. /// The ID of the object. /// /// An IPortableDeviceKeyCollection interface that holds a collection of PROPERTYKEY values specifying resource types /// supported by this object type. If the object cannot hold resources, this will be an empty collection. The caller must /// release this interface when it is done with it. /// /// /// The list of resources returned by this method includes all resources that the object can support. This does not mean that /// all the listed resources actually have data, but that the object is capable of supporting each listed resource. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceresources-getsupportedresources // HRESULT GetSupportedResources( [in] LPCWSTR pszObjectID, [out] IPortableDeviceKeyCollection **ppKeys ); IPortableDeviceKeyCollection GetSupportedResources([MarshalAs(UnmanagedType.LPWStr)] string pszObjectID); /// The GetResourceAttributes method retrieves all attributes from a specified resource in an object. /// The object ID of the object hosting the resource. /// A REFPROPERTYKEY that specifies which resource to query. /// /// Pointer to an IPortableDeviceValues interface pointer that holds PROPERTYKEY/ PROPVARIANT pairs that describe /// each attribute and its value, respectively. The value types of the attribute values vary. If a property could not be /// returned, the value for the returned property will be VT_ERROR, and the PROPVARIANT scode member will contain /// the HRESULT of that particular failure. /// /// /// Resource attributes describe the access rights, size, format, and other information related to a resource. For example, the /// attributes for an audio annotation resource on an image object may specify the bit rate, channel count, and data format of /// the audio. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceresources-getresourceattributes // HRESULT GetResourceAttributes( [in] LPCWSTR pszObjectID, [in] REFPROPERTYKEY Key, [out] IPortableDeviceValues // **ppResourceAttributes ); IPortableDeviceValues GetResourceAttributes([MarshalAs(UnmanagedType.LPWStr)] string pszObjectID, in PROPERTYKEY Key); /// /// The GetStream method gets an IStream interface with which to read or write the content data in an object on a /// device. The retrieved interface enables you to read from or write to the object data. /// /// The object ID of the object. /// /// A REFPROPERTYKEY that specifies which resource to read. You can retrieve the keys of all the object's resources by /// calling GetSupportedResources. /// /// /// One of the following access modes: /// /// /// STGM_READ (Read-only access.) /// /// /// STGM_WRITE (Write-only access.) /// /// /// STGM_READWRITE (Read/write access.) /// /// /// /// /// An optional pointer to a DWORD that specifies an estimate of the best buffer size to use when reading or writing data /// by using ppStream. A driver is required to support this value. /// /// /// Pointer to an IStream interface pointer. This interface is used to read and write data to the object. The caller must /// release this interface when it is done with it. /// /// /// /// The retrieved stream cannot read the contents of a folder recursively. To copy all the resources in an object, specify /// WPD_RESOURCE_DEFAULT for Key. /// /// If the object does not support resources, this method will return an error, and ppStream will be NULL. /// /// Applications should use the buffer size returned by pdwOptimalBufferSize when allocating the buffer for read or write operations. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceresources-getstream // HRESULT GetStream( [in] LPCWSTR pszObjectID, [in] REFPROPERTYKEY Key, [in] const DWORD dwMode, [in, out] DWORD // *pdwOptimalBufferSize, [out] IStream **ppStream ); IStream GetStream([MarshalAs(UnmanagedType.LPWStr)] string pszObjectID, in PROPERTYKEY Key, STGM dwMode, out uint pdwOptimalBufferSize); /// The Delete method deletes one or more resources from the object identified by the pszObjectID parameter. /// The object ID of the object. /// /// Pointer to an IPortableDeviceKeyCollection interface that lists which resources to delete. You can find out what resources /// the object has by calling GetSupportedResources. /// /// /// /// An object can have several resources. For instance, an object may contain image data, thumbnail image data, and audio data. /// /// An application can retrieve a list of supported resources by calling the GetSupportedResources method. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceresources-delete // HRESULT Delete( [in] LPCWSTR pszObjectID, [in] IPortableDeviceKeyCollection *pKeys ); void Delete([MarshalAs(UnmanagedType.LPWStr)] string pszObjectID, IPortableDeviceKeyCollection pKeys); /// The Cancel method cancels a pending operation. /// /// This method cancels all pending operations on the current device handle, which corresponds to a session associated with an /// IPortableDevice interface. The Windows Portable Devices (WPD) API does not support targeted cancellation of specific operations. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceresources-cancel // HRESULT Cancel(); void Cancel(); /// The CreateResource method creates a resource. /// /// Pointer to the following object parameter attributes. /// /// /// Attribute /// Description /// /// /// WPD_OBJECT_NAME /// The object name. /// /// /// WPD_RESOURCE_ATTRIBUTE_TOTAL_SIZE /// The total size of the resource data stream. /// /// /// WPD_RESOURCE_ATTRIBUTE_FORMAT /// The format of the resource data stream. /// /// /// WPD_RESOURCE_ATTRIBUTE_RESOURCE_KEY /// The resource key. /// /// /// /// Pointer to a stream into which the caller can write resource data. /// /// Pointer to a value that specifies the optimal buffer size when writing to the stream. This parameter is optional. /// /// Pointer to a cookie that identifies the resource creation request. This parameter is optional. /// /// /// When an application calls this method, it must specify the resource attributes and it must write the required data to the /// stream that this method returns. /// /// /// A resource is not created when the method returns; it is created when the application commits the data by calling the /// Commit method on the stream at which ppData points. /// /// /// To cancel the data transfer to a resource, the application must call the Revert method on the stream at which ppData /// points. Once the transfer is canceled, the application must invoke IUnknown::Release to close the stream. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceresources-createresource // HRESULT CreateResource( [in] IPortableDeviceValues *pResourceAttributes, [out] IStream **ppData, [out] DWORD // *pdwOptimalWriteBufferSize, [out] LPWSTR *ppszCookie ); void CreateResource(IPortableDeviceValues pResourceAttributes, out IStream ppData, out uint pdwOptimalWriteBufferSize, [MarshalAs(UnmanagedType.LPWStr)] out string ppszCookie); } /// The IPortableDeviceService interface provides access to a service. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nn-portabledeviceapi-iportabledeviceservice [PInvokeData("portabledeviceapi.h", MSDNShortId = "NN:portabledeviceapi.IPortableDeviceService")] [ComImport, Guid("D3BD3A44-D7B5-40A9-98B7-2FA4D01DEC08"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), CoClass(typeof(PortableDeviceService))] public interface IPortableDeviceService { /// The Open method opens a connection to the service. /// /// The Plug and Play (PnP) identifier for the service, which is the same identifier that is retrieved by the GetPnPServiceId method. /// /// The IPortableDeviceValues interface specifying the client information. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservice-open HRESULT // Open( [in] LPCWSTR pszPnPServiceID, [in] IPortableDeviceValues *pClientInfo ); void Open([MarshalAs(UnmanagedType.LPWStr)] string pszPnPServiceID, IPortableDeviceValues pClientInfo); /// The Capabilities method retrieves the service capabilities. /// The IPortableDeviceServiceCapabilities interface specifying the capabilities of the service. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservice-capabilities // HRESULT Capabilities( [out] IPortableDeviceServiceCapabilities **ppCapabilities ); IPortableDeviceServiceCapabilities Capabilities(); /// The Content method retrieves access to the service content. /// The IPortableDeviceContent2 interface that accesses the service content. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservice-content // HRESULT Content( [out] IPortableDeviceContent2 **ppContent ); IPortableDeviceContent2 Content(); /// /// The Methods method retrieves the IPortableDeviceServiceMethods interface that is used to invoke custom functionality /// on the service. /// /// The IPortableDeviceServiceMethods interface used for invoking methods on the given service. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservice-methods // HRESULT Methods( [out] IPortableDeviceServiceMethods **ppMethods ); IPortableDeviceServiceMethods Methods(); /// The Cancel method cancels a pending operation on this interface. /// /// /// This method cancels all pending operations on the current device handle, which corresponds to a session associated with an /// IPortableDeviceService interface. The Windows Portable Devices (WPD) API does not support targeted cancellation of specific operations. /// /// /// If your application invokes the WPD API from multiple threads, each thread should create a new instance of the /// IPortableDeviceService interface. Doing this ensures that any cancel operation affects only the I/O for the affected thread. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservice-cancel // HRESULT Cancel(); void Cancel(); /// The Close method releases the connection to the service. /// /// /// Applications typically won't call this method, as the Windows Portable Devices (WPD) API automatically calls it when the /// last reference to a service is removed. /// /// /// When an application does call this method, the WPD API releases the service connection, so that any WPD objects attached to /// the service will return the E_WPD_SERVICE_NOT_OPEN error. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservice-close // HRESULT Close(); void Close(); /// /// The GetServiceObjectID method retrieves an object identifier for the service. This object identifier can be used to /// access the properties of the service, for example. /// /// The retrieved service object identifier. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservice-getserviceobjectid // HRESULT GetServiceObjectID( [out] LPWSTR *ppszServiceObjectID ); [return: MarshalAs(UnmanagedType.LPWStr)] string GetServiceObjectID(); /// The GetPnPServiceID method retrieves a Plug and Play (PnP) identifier for the service. /// The retrieved PnP identifier, which is the same identifier that was passed to the Open method. /// /// The Open method must be called on the service before a PnP identifier can be retrieved. /// /// When an application no longer needs the PnP identifier, it should call the CoTaskMemFree function to free the /// identifier memory. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservice-getpnpserviceid // HRESULT GetPnPServiceID( [out] LPWSTR *ppszPnPServiceID ); [return: MarshalAs(UnmanagedType.LPWStr)] string GetPnPServiceID(); /// The Advise method registers an application-defined callback object that receives service events. /// Not used. /// The IPortableDeviceEventCallback interface specifying the callback object to register. /// /// The IPortableDeviceValues interface specifying the event-registration parameters, or NULL if the callback object is /// to receive all service events. /// /// /// The unique context ID for the callback object. This value matches that used by the Unadvise method to unregister the /// callback object. /// /// /// During cleanup, an application should unregister the callback object by calling the Unadvise method, and then release the /// memory referenced by the ppszCookie parameter by calling the CoTaskMemFree function. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservice-advise // HRESULT Advise( [in] const DWORD dwFlags, [in] IPortableDeviceEventCallback *pCallback, [in] IPortableDeviceValues // *pParameters, [out] LPWSTR *ppszCookie ); void Advise([In, Optional] uint dwFlags, IPortableDeviceEventCallback pCallback, [In, Optional] IPortableDeviceValues? pParameters, [MarshalAs(UnmanagedType.LPWStr)] out string ppszCookie); /// The Unadvise method unregisters a service event callback object. /// /// The unique context ID for the application-supplied callback object. This value matches that yielded by the ppszCookie /// parameter of the Advise method. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservice-unadvise // HRESULT Unadvise( [in] LPCWSTR pszCookie ); void Unadvise([MarshalAs(UnmanagedType.LPWStr)] string pszCookie); /// The SendCommand method sends a standard WPD command and its parameters to the service. /// Not used. /// The IPortableDeviceValues interface specifying the command parameters. /// The IPortableDeviceValues interface specifying the command results. /// /// /// This method should only be used to send standard WPD commands to the service. To invoke service methods, use the /// IPortableDeviceServiceMethods interface. /// /// /// This method may fail even though it returns S_OK as its HRESULT value. To determine if a command succeeded, an /// application should always examine the properties referenced by the ppResults parameter: /// /// /// /// The WPD_PROPERTY_COMMON_HRESULT property indicates if the command succeeded. /// /// /// If the command failed, the WPD_PROPERTY_COMMON_DRIVER_ERROR_CODE property will contain driver-specific error codes. /// /// /// The object referenced by the pParameters parameter must specify at least these properties: /// /// /// /// WPD_PROPERTY_COMMON_COMMAND_CATEGORY, which should contain a command category, such as the fmtid member of the /// WPD_COMMAND_COMMON_RESET_DEVICE property /// /// /// /// /// WPD_PROPERTY_COMMON_COMMAND_ID, which should contain a command identifier, such as the pid member of the /// WPD_COMMAND_COMMON_RESET_DEVICE property. /// /// /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservice-sendcommand // HRESULT SendCommand( [in] const DWORD dwFlags, [in] IPortableDeviceValues *pParameters, [out] IPortableDeviceValues // **ppResults ); void SendCommand([In, Optional] uint dwFlags, IPortableDeviceValues pParameters, out IPortableDeviceValues ppResults); } /// /// Clients use this interface to asynchronously open an IPortableDeviceService instance. This is used when opening a service can /// involve a user consent prompt. /// [PInvokeData("portabledeviceapi.h")] [ComImport, Guid("e56b0534-d9b9-425c-9b99-75f97cb3d7c8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPortableDeviceServiceActivation { /// [PreserveSig] HRESULT OpenAsync([MarshalAs(UnmanagedType.LPWStr)] string pszPnPServiceID, IPortableDeviceValues pClientInfo, IPortableDeviceServiceOpenCallback pCallback); /// [PreserveSig] HRESULT CancelOpenAsync(); } /// The IPortableDeviceServiceCapabilities interface retrieves information describing the capabilities of a service. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nn-portabledeviceapi-iportabledeviceservicecapabilities [PInvokeData("portabledeviceapi.h", MSDNShortId = "NN:portabledeviceapi.IPortableDeviceServiceCapabilities")] [ComImport, Guid("24DBD89D-413E-43E0-BD5B-197F3C56C886"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPortableDeviceServiceCapabilities { /// The GetSupportedMethods method retrieves the methods supported by the service. /// The IPortableDevicePropVariantCollection interface that receives the list of methods. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicecapabilities-getsupportedmethods // HRESULT GetSupportedMethods( [out] IPortableDevicePropVariantCollection **ppMethods ); IPortableDevicePropVariantCollection GetSupportedMethods(); /// /// The GetSupportedMethodsByFormat method retrieves the methods supported by the service for the specified format. /// /// The format whose supported methods are retrieved. /// The IPortableDevicePropVariantCollection interface that receives the list of methods. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicecapabilities-getsupportedmethodsbyformat // HRESULT GetSupportedMethodsByFormat( [in] REFGUID Format, [out] IPortableDevicePropVariantCollection **ppMethods ); IPortableDevicePropVariantCollection GetSupportedMethodsByFormat(in Guid Format); /// The GetMethodAttributes method retrieves the attributes used to describe a given method. /// The method whose attributes are retrieved. /// The IPortableDeviceValues interface that receives the list of attributes. /// /// /// Possible attributes include the WPD_METHOD_ATTRIBUTE_NAME, WPD_METHOD_ATTRIBUTE_ASSOCIATED_FORMAT, /// WPD_METHOD_ATTRIBUTE_ACCESS, and WPD_METHOD_ATTRIBUTE_PARAMETERS properties. /// /// Examples /// For an example of how to use this method, see Retrieving Supported Service Methods. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicecapabilities-getmethodattributes // HRESULT GetMethodAttributes( [in] REFGUID Method, [out] IPortableDeviceValues **ppAttributes ); IPortableDeviceValues GetMethodAttributes(in Guid Method); /// The GetMethodParameterAttributes method retrieves the attributes used to describe a given method parameter. /// The method that contains the parameter whose attributes are retrieved. /// The parameter whose attributes are retrieved. /// The IPortableDeviceValues interface that receives the list of attributes. /// /// /// Possible attributes include the WPD_PARAMETER_ATTRIBUTE_ORDER, WPD_PARAMETER_ATTRIBUTE_USAGE, /// WPD_PARAMETER_ATTRIBUTE_NAME, and WPD_PARAMETER_ATTRIBUTE_VARTYPE properties. /// /// Examples /// For an example of how to use this method, see Retrieving Supported Service Methods. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicecapabilities-getmethodparameterattributes // HRESULT GetMethodParameterAttributes( REFGUID Method, [in] REFPROPERTYKEY Parameter, [out] IPortableDeviceValues // **ppAttributes ); IPortableDeviceValues GetMethodParameterAttributes(in Guid Method, in PROPERTYKEY Parameter); /// The GetSupportedFormats method retrieves the formats supported by the service. /// The IPortableDevicePropVariantCollection interface that receives the list of formats. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicecapabilities-getsupportedformats // HRESULT GetSupportedFormats( [out] IPortableDevicePropVariantCollection **ppFormats ); IPortableDevicePropVariantCollection GetSupportedFormats(); /// The GetFormatAttributes method retrieves the attributes of a format. /// The format whose attributes are retrieved. /// The IPortableDeviceValues interface that receives the list of attributes. /// /// WPD_FORMAT_ATTRIBUTE_NAME is an example of a commonly retrieved attribute. /// Examples /// For an example of how to use this method, see Retrieving Supported Service Formats. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicecapabilities-getformatattributes // HRESULT GetFormatAttributes( [in] REFGUID Format, [out] IPortableDeviceValues **ppAttributes ); IPortableDeviceValues GetFormatAttributes(in Guid Format); /// /// The GetSupportedFormatProperties method retrieves the properties supported by the service for the specified format. /// /// The format whose properties are retrieved. /// The IPortableDeviceKeyCollection interface that receives the list of properties. /// /// The retrieved property collection is a superset of all properties supported by an object of the specified format. /// /// An application can also retrieve the properties for an object by calling the IPortableDeviceService::SendCommand method with /// the WPD_COMMAND_OBJECT_PROPERTIES_GET_SUPPORTED property passed as the command identifier. However, the /// GetSupportedFormatProperties method is typically faster than the IPortableDeviceService::SendCommand method. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicecapabilities-getsupportedformatproperties // HRESULT GetSupportedFormatProperties( [in] REFGUID Format, [out] IPortableDeviceKeyCollection **ppKeys ); IPortableDeviceKeyCollection GetSupportedFormatProperties(in Guid Format); /// The GetFormatPropertyAttributes method retrieves the attributes of a format property. /// The format whose property has its attributes retrieved. /// The property whose attributes are retrieved. /// The IPortableDeviceValues interface that receives the list of attributes. /// /// /// A Windows Portable Devices (WPD) driver often treats objects of a given format the same. Many properties will therefore have /// attributes that are identical across all objects of that format. This method retrieves such attributes. /// /// Note that this method will not retrieve attributes that differ across object instances. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicecapabilities-getformatpropertyattributes // HRESULT GetFormatPropertyAttributes( [in] REFGUID Format, [in] REFPROPERTYKEY Property, [out] IPortableDeviceValues // **ppAttributes ); IPortableDeviceValues GetFormatPropertyAttributes(in Guid Format, in PROPERTYKEY Property); /// The GetSupportedEvents method retrieves the events supported by the service. /// The IPortableDevicePropVariantCollection interface that receives the list of events. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicecapabilities-getsupportedevents // HRESULT GetSupportedEvents( [out] IPortableDevicePropVariantCollection **ppEvents ); IPortableDevicePropVariantCollection GetSupportedEvents(); /// The GetEventAttributes method retrieves the attributes of an event. /// The event whose attributes are retrieved. /// The IPortableDeviceValues interface that receives the list of attributes. /// /// /// Possible attributes include the WPD_EVENT_ATTRIBUTE_NAME, WPD_EVENT_ATTRIBUTE_PARAMETERS, and WPD_EVENT_ATTRIBUTE_OPTIONS properties. /// /// Examples /// For an example of how to use this method, see Retrieving Supported Service Events. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicecapabilities-geteventattributes // HRESULT GetEventAttributes( [in] REFGUID Event, [out] IPortableDeviceValues **ppAttributes ); IPortableDeviceValues GetEventAttributes(in Guid Event); /// The GetEventParameterAttributes method retrieves the attributes of an event parameter. /// The event that contains the parameter whose attributes are retrieved. /// The parameter whose attributes are retrieved. /// The IPortableDeviceValues interface that receives the list of attributes. /// /// Possible attribute values include the WPD_PARAMETER_ATTRIBUTE_VARTYPE and WPD_PARAMETER_ATTRIBUTE_FORM properties. /// Examples /// For an example of how to use this method, see Retrieving Supported Service Events. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicecapabilities-geteventparameterattributes // HRESULT GetEventParameterAttributes( REFGUID Event, [in] REFPROPERTYKEY Parameter, [out] IPortableDeviceValues **ppAttributes ); IPortableDeviceValues GetEventParameterAttributes(in Guid Event, in PROPERTYKEY Parameter); /// The GetInheritedServices method retrieves the services having the specified inheritance type. /// The type of inherited services to retrieve. /// /// The IPortableDevicePropVariantCollection interface that receives the list of services. If no inherited services are found, /// an empty collection is returned. /// /// /// /// Currently, device services may only inherit by implementing an abstract service. This is analogous to how a class implements /// methods of an abstract interface or a virtual class in object-oriented programming. By implementing an abstract service, a /// device service will support all formats, properties, and method behavior that the abstract service describes. For instance, /// a Contacts service may implement the Anchor Sync abstract service, where the device stores markers indicating /// which contacts were updated since the last synchronization with the PC. /// /// /// Possible values for the dwInheritanceType parameter are those defined in the WPD_SERVICE_INHERITANCE_TYPES enumeration. (For /// Windows 7, only the WPD_SERVICE_INHERITANCE_IMPLEMENTATION enumeration constant is supported.) /// /// /// If the value of the dwInheritanceType parameter is WPD_SERVICE_INHERITANCE_IMPLEMENTATION, each item in the /// collection specified by the ppServices parameter has variant type VT_CLSID. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicecapabilities-getinheritedservices // HRESULT GetInheritedServices( [in] const DWORD dwInheritanceType, [out] IPortableDevicePropVariantCollection **ppServices ); IPortableDevicePropVariantCollection GetInheritedServices([In] WPD_SERVICE_INHERITANCE_TYPES dwInheritanceType); /// The GetFormatRenderingProfiles method retrieves the rendering profiles of a format. /// The format whose rendering profiles are retrieved. /// The IPortableDeviceValuesCollection object that receives the list of rendering profiles. /// /// The rendering profiles are similar to what the WPD_FUNCTIONAL_CATEGORY_RENDERING_INFORMATION functional object returns for /// device-wide rendering profiles, so that the DisplayRenderingProfile helper function described in Retrieving the /// Rendering Capabilities Supported by a Device could be used here as well. But there are differences: The /// GetFormatRenderingProfiles method retrieves only rendering profiles that apply to the selected service and have been /// filtered by format. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicecapabilities-getformatrenderingprofiles // HRESULT GetFormatRenderingProfiles( [in] REFGUID Format, [out] IPortableDeviceValuesCollection **ppRenderingProfiles ); IPortableDeviceValuesCollection GetFormatRenderingProfiles(in Guid Format); /// The GetSupportedCommands method retrieves the commands supported by the service. /// The IPortableDeviceKeyCollection interface that receives the list of commands. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicecapabilities-getsupportedcommands // HRESULT GetSupportedCommands( [out] IPortableDeviceKeyCollection **ppCommands ); IPortableDeviceKeyCollection GetSupportedCommands(); /// The GetCommandOptions method retrieves the options of a WPD command. /// The command whose options are retrieved. /// The IPortableDeviceValues interface that receives the list of options. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicecapabilities-getcommandoptions // HRESULT GetCommandOptions( [in] REFPROPERTYKEY Command, [out] IPortableDeviceValues **ppOptions ); IPortableDeviceValues GetCommandOptions(in PROPERTYKEY Command); /// The Cancel method cancels a pending operation. /// /// This method cancels all pending operations on the current service handle, which corresponds to a session associated with an /// IPortableDeviceService interface. The Windows Portable Devices (WPD) API does not support targeted cancellation of specific operations. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicecapabilities-cancel // HRESULT Cancel(); void Cancel(); } /// /// The IPortableDeviceServiceManager interface retrieves the device associated with a service and the list of services found /// on a device. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nn-portabledeviceapi-iportabledeviceservicemanager [PInvokeData("portabledeviceapi.h", MSDNShortId = "NN:portabledeviceapi.IPortableDeviceServiceManager")] [ComImport, Guid("a8abc4e9-a84a-47a9-80b3-c5d9b172a961"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPortableDeviceServiceManager { /// The GetDeviceServices method retrieves a list of the services associated with the specified device. /// The Plug and Play (PnP) identifier of the device. /// /// A reference to a globally unique identifier (GUID) that specifies the category of services to retrieve. If the referenced /// identifier is GUID_DEVINTERFACE_WPD_SERVICE, this method will retrieve all services supported by the device. /// /// /// A user-allocated array of pointers to strings. When the method returns, the array contains the retrieved PnP service identifiers. /// /// /// The number of elements in the array specified by the pServices parameter. This value represents the maximum number of /// service identifiers that will be retrieved. When the method returns, this parameter contains the number of identifiers /// actually retrieved. /// /// /// /// If this method succeeds, the application should call the FreePortableDevicePnPIDs function to free the array referenced by /// the pServices parameter. /// /// An application can retrieve the PnP identifier for a device by calling the IPortableDeviceManager::GetDevices method. /// /// Applications that use Single Threaded Apartments should use CLSID_PortableDeviceServiceFTM as this eliminates the /// overhead of interface pointer marshaling. CLSID_PortableDeviceService is still supported for legacy applications. /// /// Examples /// The following example shows how to retrieve a list of services for all devices. /// /// #include "stdafx.h" #include "atlbase.h" #include "portabledeviceapi.h" #include "portabledevice.h" HRESULT GetServiceName( LPCWSTR pszPnpServiceID, LPWSTR* ppszServiceName); HRESULT EnumerateServicesForDevice( IPortableDeviceServiceManager* pPortableDeviceServiceManager, LPCWSTR pszPnpDeviceID); int _tmain(int argc, _TCHAR* argv[]) { HRESULT hr = S_OK; DWORD cPnPDeviceIDs = 0; LPWSTR* pPnpDeviceIDs = NULL; CComPtr<IPortableDeviceManager> pPortableDeviceManager; CComPtr<IPortableDeviceServiceManager> pPortableDeviceServiceManager; // Initialize COM for COINIT_MULTITHREADED hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); // CoCreate the IPortableDeviceManager interface to enumerate // portable devices and to get information about them. if (hr == S_OK) { hr = CoCreateInstance(CLSID_PortableDeviceManager, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDeviceManager, (VOID**) &pPortableDeviceManager); } if (hr == S_OK) { // Get the PortableDeviceServiceManager interface // by calling QueryInterface from IPortableDeviceManager hr = pPortableDeviceManager->QueryInterface (IID_IPortableDeviceServiceManager, (VOID**) &pPortableDeviceServiceManager); } // Get the number of devices on the system if (hr == S_OK) { hr = pPortableDeviceManager->GetDevices(NULL, &cPnPDeviceIDs); } // If we have at least 1 device, // continue to query the list of services for each device if ((hr == S_OK) && (cPnPDeviceIDs > 0)) { pPnpDeviceIDs = new LPWSTR[cPnPDeviceIDs]; if (pPnpDeviceIDs != NULL) { hr = pPortableDeviceManager->GetDevices (pPnpDeviceIDs, &cPnPDeviceIDs); if (SUCCEEDED(hr)) { for (DWORD dwIndex = 0; dwIndex < cPnPDeviceIDs; dwIndex++) { hr = EnumerateServicesForDevice (pPortableDeviceServiceManager, pPnpDeviceIDs[dwIndex]); } } // Free all returned PnPDeviceID strings FreePortableDevicePnPIDs(pPnpDeviceIDs, cPnPDeviceIDs); // Delete the array of LPWSTR pointers delete [] pPnpDeviceIDs; pPnpDeviceIDs = NULL; } } return 0; } HRESULT EnumerateServicesForDevice( IPortableDeviceServiceManager* pPortableDeviceServiceManager, LPCWSTR pszPnpDeviceID) { HRESULT hr = S_OK; DWORD cPnpServiceIDs = 0; LPWSTR* pPnpServiceIDs = NULL; if (pPortableDeviceServiceManager == NULL) { return E_POINTER; } // Get the number of services for the device if (hr == S_OK) { hr = pPortableDeviceServiceManager->GetDeviceServices( pszPnpDeviceID, GUID_DEVINTERFACE_WPD_SERVICE, NULL, &cPnpServiceIDs); } // If we have at least 1, continue to gather information about // each service and populate the device information array. if ((hr == S_OK) && (cPnpServiceIDs > 0)) { pPnpServiceIDs = new LPWSTR[cPnpServiceIDs]; if (pPnpServiceIDs != NULL) { // Get a list of all services on the given device. // To query a give type of service (e.g. the Contacts Service), // a service GUID can be provided here instead of // GUID_DEVINTERFACE_WPD_SERVICE which returns all services DWORD dwIndex = 0; hr = pPortableDeviceServiceManager->GetDeviceServices (pszPnpDeviceID, GUID_DEVINTERFACE_WPD_SERVICE, pPnpServiceIDs, &cPnpServiceIDs); if (SUCCEEDED(hr)) { // For each service found, read the name property for (dwIndex = 0; dwIndex < cPnpServiceIDs && SUCCEEDED(hr); dwIndex++) { LPWSTR pszServiceName = NULL; hr = GetServiceName(pPnpServiceIDs[dwIndex], &pszServiceName); CoTaskMemFree(pszServiceName); } } FreePortableDevicePnPIDs(pPnpServiceIDs, cPnpServiceIDs); // Delete the array of LPWSTR pointers delete [] pPnpServiceIDs; pPnpServiceIDs = NULL; } } } HRESULT GetServiceName( LPCWSTR pszPnpServiceID, LPWSTR* ppszServiceName) { HRESULT hr = S_OK; LPWSTR pszServiceID = NULL; LPWSTR pszServiceObjectID = NULL; CComPtr<IPortableDeviceValues> pClientInfo; CComPtr<IPortableDeviceValues> pPropertyValues; CComPtr<IPortableDeviceService> pService; CComPtr<IPortableDeviceContent2> pContent; CComPtr<IPortableDeviceProperties>pProperties; CComPtr<IPortableDeviceKeyCollection> pPropertiesToRead; hr = CoCreateInstance(CLSID_PortableDeviceServiceFTM, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDeviceService, (VOID**) &pService); if (hr == S_OK) { // CoCreate an IPortableDeviceValues interface // to hold the client information. hr = CoCreateInstance(CLSID_PortableDeviceValues, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDeviceValues, (VOID**) & pClientInfo); if ((hr == S_OK) && (pClientInfo!= NULL)) { hr = pClientInfo->SetStringValue (WPD_CLIENT_NAME, L"Service Sample Application"); if (hr == S_OK) { hr = pClientInfo->SetUnsignedIntegerValue( WPD_CLIENT_MAJOR_VERSION, 1); } if (hr == S_OK) { hr = pClientInfo->SetUnsignedIntegerValue( WPD_CLIENT_MINOR_VERSION, 0); } if (hr == S_OK) { hr = pClientInfo->SetUnsignedIntegerValue( WPD_CLIENT_REVISION, 0); } if (hr == S_OK) { hr = pClientInfo->SetUnsignedIntegerValue( WPD_CLIENT_SECURITY_QUALITY_OF_SERVICE, SECURITY_IMPERSONATION); } if (hr == S_OK) { // Open a connection to the service hr = pService->Open(pszPnpServiceID, pClientInfo); } if (hr == S_OK) { hr = pService->GetServiceObjectID(&pszServiceID); } if (hr == S_OK) { hr = pService->Content(&pContent); } if (hr == S_OK) { hr = pContent->Properties(&pProperties); } // Create a IPortableDeviceKeyCollection // containing the single PROPERTYKEY if (hr == S_OK) { hr = CoCreateInstance(CLSID_PortableDeviceKeyCollection, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDeviceKeyCollection, (VOID**) &pPropertiesToRead); } // Add our property key if (hr == S_OK) { hr = pPropertiesToRead->Add(WPD_OBJECT_NAME); } if (hr == S_OK) { hr = pProperties->GetValues( pszServiceID, pPropertiesToRead, &pPropertyValues); } if (hr == S_OK) { hr = pPropertyValues->GetStringValue( WPD_OBJECT_NAME, ppszServiceName); } CoTaskMemFree(pszServiceObjectID); return hr; } } } /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicemanager-getdeviceservices // HRESULT GetDeviceServices( [in] LPCWSTR pszPnPDeviceID, [in] REFGUID guidServiceCategory, [in, out] LPWSTR *pServices, [in, // out] DWORD *pcServices ); void GetDeviceServices([MarshalAs(UnmanagedType.LPWStr)] string pszPnPDeviceID, in Guid guidServiceCategory, [Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] string[] pServices, ref uint pcServices); /// The GetDeviceForService method retrieves the device associated with the specified service. /// The Plug and Play (PnP) identifier of the service. /// The retrieved PnP identifier of the device associated with the service. /// /// Neither the pszPnPServiceID parameter nor the pszPnPDeviceID parameter can be NULL. /// An application can retrieve a PnP service identifier by calling the GetDeviceServices method. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicemanager-getdeviceforservice // HRESULT GetDeviceForService( [in] LPCWSTR pszPnPServiceID, [out] LPWSTR *ppszPnPDeviceID ); [return: MarshalAs(UnmanagedType.LPWStr)] string GetDeviceForService([MarshalAs(UnmanagedType.LPWStr)] string pszPnPServiceID); } /// /// /// The IPortableDeviceServiceMethodCallback interface contains a method that applications use to track the completion of a /// callback method. Applications that call service methods asynchronously may implement this interface, and supply it as a /// parameter to IPortableDeviceServiceMethods::InvokeAsync. /// /// /// Each asynchronous method invocation uses the application-supplied callback object as its context. Therefore, an application that /// intends to simultaneously invoke multiple methods should avoid reusing the callback object. Instead, the application should /// provide a unique instance of the callback object for each call to InvokeAsync /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nn-portabledeviceapi-iportabledeviceservicemethodcallback [PInvokeData("portabledeviceapi.h", MSDNShortId = "NN:portabledeviceapi.IPortableDeviceServiceMethodCallback")] [ComImport, Guid("C424233C-AFCE-4828-A756-7ED7A2350083"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPortableDeviceServiceMethodCallback { /// The OnComplete method indicates that a callback method has completed execution. /// The overall status of the method. /// /// An IPortableDeviceValues interface that contains the method-execution results. This is empty if the method returns no results. /// /// If the method succeeds, it returns S_OK. Any other HRESULT value indicates that the call failed. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicemethodcallback-oncomplete // HRESULT OnComplete( [in] HRESULT hrStatus, [in] IPortableDeviceValues *pResults ); [PreserveSig] HRESULT OnComplete(HRESULT hrStatus, IPortableDeviceValues pResults); } /// The IPortableDeviceServiceMethods interface invokes, or cancels invocation of, a method on a service. // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nn-portabledeviceapi-iportabledeviceservicemethods [PInvokeData("portabledeviceapi.h", MSDNShortId = "NN:portabledeviceapi.IPortableDeviceServiceMethods")] [ComImport, Guid("E20333C9-FD34-412D-A381-CC6F2D820DF7"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPortableDeviceServiceMethods { /// The Invoke method synchronously invokes a method. /// The method to invoke. /// /// A pointer to an IPortableDeviceValues interface that contains the parameters of the invoked method, or NULL to /// indicate that the method has no parameters. /// /// /// The address of a pointer to an IPortableDeviceValues interface that receives the method results, or NULL to ignore /// the method results. /// /// /// /// The method invocation is synchronous and will not return until the method has completed. For long-running methods, your /// application should call the InvokeAsync method instead. /// /// Examples /// For an example of how to use this method, see Invoking Service Methods /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicemethods-invoke // HRESULT Invoke( [in] REFGUID Method, [in] IPortableDeviceValues *pParameters, [in, out] IPortableDeviceValues **ppResults ); void Invoke(in Guid Method, [Optional] IPortableDeviceValues? pParameters, out IPortableDeviceValues ppResults); /// The InvokeAsync method asynchronously invokes a method. /// The method to invoke. /// /// A pointer to an IPortableDeviceValues interface that contains the parameters of the invoked method, or NULL to /// indicate that the method has no parameters. /// /// /// A pointer to an application-supplied IPortableDeviceServiceMethodCallback callback object that receives the method results, /// or NULL to ignore the method results. /// /// /// /// When invoking multiple methods, clients can create a separate instance of the IPortableDeviceServiceMethodCallback interface /// for each invocation, saving a context with that instance object before passing it to the InvokeAsync method. This /// way, the method operation can be identified when the OnComplete method is called. Use of a unique object for each invocation /// also allows targeted cancellation of an operation by the Cancel method. /// /// Examples /// For an example of how to use this method, see Invoking Service Methods Asynchronously. /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicemethods-invokeasync // HRESULT InvokeAsync( [in] REFGUID Method, [in] IPortableDeviceValues *pParameters, [in] IPortableDeviceServiceMethodCallback // *pCallback ); void InvokeAsync(in Guid Method, [Optional] IPortableDeviceValues? pParameters, [Optional] IPortableDeviceServiceMethodCallback? pCallback); /// The Cancel method cancels a pending method invocation. /// /// A pointer to the callback object whose method invocation is to be canceled, or NULL to cancel all pending method invocations. /// /// /// /// A callback object identifies a method invocation. If the same callback object is reused for multiple calls to the /// InvokeAsync method, all method invocations arising from these calls will be cancelled. /// /// /// To enable targeted cancellation of a specific method invocation, pass a unique instance of the /// IPortableDeviceServiceMethodCallback interface to the InvokeAsync method. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicemethods-cancel // HRESULT Cancel( [in] IPortableDeviceServiceMethodCallback *pCallback ); void Cancel([Optional] IPortableDeviceServiceMethodCallback? pCallback); } /// Callback interface for implemented by clients for retrieving results of an asynchronous service open. [PInvokeData("portabledeviceapi.h")] [ComImport, Guid("bced49c8-8efe-41ed-960b-61313abd47a9"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPortableDeviceServiceOpenCallback { /// [PreserveSig] HRESULT OnComplete(HRESULT hrStatus); } /// Enumerates the items in the collection. /// The instance. /// A sequence of values from the collection. public static IEnumerable Enumerate(this IEnumPortableDeviceObjectIDs intf) => new Vanara.Collections.IEnumFromCom(intf.Next, intf.Reset); /// Retrieves the description of a device. /// The instance used to get the name. /// The device's Plug and Play ID. /// The user-description name of the device. public static string GetDeviceDescription(this IPortableDeviceManager manager, string pszPnPDeviceID) => PDMGetString(manager.GetDeviceDescription, pszPnPDeviceID); /// Retrieves the user-friendly name for the device. /// The instance used to get the name. /// The device's Plug and Play ID. /// The user-friendly name for the device. /// /// A device is not required to support this method. If this method fails to retrieve a name, try requesting the WPD_OBJECT_NAME /// property of the device object (the object with the ID WPD_DEVICE_OBJECT_ID). /// public static string GetDeviceFriendlyName(this IPortableDeviceManager manager, string pszPnPDeviceID) => PDMGetString(manager.GetDeviceFriendlyName, pszPnPDeviceID); /// Retrieves the name of the device manufacturer. /// The instance used to get the name. /// The device's Plug and Play ID. /// The name of the device manufacturer. public static string GetDeviceManufacturer(this IPortableDeviceManager manager, string pszPnPDeviceID) => PDMGetString(manager.GetDeviceManufacturer, pszPnPDeviceID); /// /// Retrieves a property value stored by the device on the computer. (These are not standard properties that are defined by Windows /// Portable Devices.) /// /// The type of the value to return. /// The instance used to get the device property. /// /// The device's Plug and Play ID. You can retrieve a list of Plug and Play names of all devices that are connected to the computer /// by calling GetDevices. /// /// /// The name of the property to request. These are custom property names defined by a device manufacturer. /// /// The retrieved data. This call will also return an error that can be ignored. See Return Values. /// /// /// These property values are stored on device installation, or stored by a device during operation so that they can be persisted /// across connection sessions. An application must know the exact name of the property, which is specified by the device itself; /// therefore, this method is intended to be used by device developers who are creating their own applications. /// /// /// To get Windows Portable Devices properties from the device object, call IPortableDeviceProperties::GetValues, and specify the /// device object with WPD_DEVICE_OBJECT_ID. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicemanager-getdeviceproperty // HRESULT GetDeviceProperty( [in] LPCWSTR pszPnPDeviceID, [in] LPCWSTR pszDevicePropertyName, [in, out] BYTE *pData, [in, out] // DWORD *pcbData, [in, out] DWORD *pdwType ); public static T? GetDeviceProperty(this IPortableDeviceManager manager, string pszPnPDeviceID, string pszDevicePropertyName) { var sz = 0U; manager.GetDeviceProperty(pszPnPDeviceID, pszDevicePropertyName, default, ref sz, out _); if (sz == 0) return default; using var mem = new SafeCoTaskMemHandle(sz); manager.GetDeviceProperty(pszPnPDeviceID, pszDevicePropertyName, mem, ref sz, out var type); return (T?)type.GetValue(mem, mem.Size); } /// Retrieves a list of portable devices connected to the computer. /// The instance used to get the list of devices. /// /// If set to , calls before retrieving the name; /// otherwise the device names will represent those available then the instance was created. /// /// /// An array of strings that holds the Plug and Play names of all of the connected devices. These names can be used by /// IPortableDevice::Open to create a connection to a device. /// public static string[] GetDevices(this IPortableDeviceManager manager, bool forceRefresh = false) { if (forceRefresh) manager.RefreshDeviceList(); return PDMGetStrings(manager.GetDevices); } /// /// Retrieves a list of private portable devices connected to the computer. These private devices are only accessible through an /// application that is designed for these particular devices. /// /// The instance used to get the list of devices. /// /// An array of strings that holds the Plug and Play names of all of the connected devices. These names can be used by /// IPortableDevice::Open to create a connection to a device. /// public static string[] GetPrivateDevices(this IPortableDeviceManager manager) => PDMGetStrings(manager.GetPrivateDevices); private static string PDMGetString(PDMStrGet func, string devId) { var cnt = 0U; var hr = func(devId, null, ref cnt); if (cnt == 0) return string.Empty; if (hr.Failed && hr != HRESULT.HRESULT_FROM_WIN32(Win32Error.ERROR_INSUFFICIENT_BUFFER)) throw hr.GetException()!; var sb = new StringBuilder((int)cnt + 1); if (cnt > 0) func(devId, sb, ref cnt).ThrowIfFailed(); return sb.ToString(); } private static string[] PDMGetStrings(PDMStrArrGet func) { var cnt = 0U; var hr = func(null, ref cnt); if (cnt == 0) return new string[0]; if (hr.Failed && hr != HRESULT.HRESULT_FROM_WIN32(Win32Error.ERROR_INSUFFICIENT_BUFFER)) throw hr.GetException()!; var devices = new string[cnt]; if (cnt > 0) func(devices, ref cnt).ThrowIfFailed(); return devices; } /// PortableDevice Class [ComImport, Guid("728a21c5-3d9e-48d7-9810-864848f0f404"), ClassInterface(ClassInterfaceType.None)] public class PortableDevice { } /// PortableDeviceDispatchFactory Class [ComImport, Guid("43232233-8338-4658-ae01-0b4ae830b6b0"), ClassInterface(ClassInterfaceType.None)] public class PortableDeviceDispatchFactory { } /// PortableDeviceFTM Class [ComImport, Guid("f7c0039a-4762-488a-b4b3-760ef9a1ba9b"), ClassInterface(ClassInterfaceType.None)] public class PortableDeviceFTM { } /// PortableDeviceManager Class [ComImport, Guid("0af10cec-2ecd-4b92-9581-34f6ae0637f3"), ClassInterface(ClassInterfaceType.None)] public class PortableDeviceManager { } /// PortableDeviceService Class [ComImport, Guid("ef5db4c2-9312-422c-9152-411cd9c4dd84"), ClassInterface(ClassInterfaceType.None)] public class PortableDeviceService { } /// PortableDeviceServiceFTM Class [ComImport, Guid("1649b154-c794-497a-9b03-f3f0121302f3"), ClassInterface(ClassInterfaceType.None)] public class PortableDeviceServiceFTM { } }