0

I'm trying to determine what type my WPD device is in Delphi.

In my application I need to know if the device is a Phone or Camera or what ever it is.

According to this MSDN article the WPD Device Type is a WPD Device Property which can be read by reading the properties of the device.

Then according to this MSDN article properties and attributes are defined as PROPERTYKEY structures with two parts: a category GUID, and a unique ID for that category.

I've found GUID and Uinique ID for WPD_DEVICE_TYPE which are WPD_DEVICE_TYPE_FMTID : TGuid = '{26D4979A-E643-4626-9E2B-736DC0C92FDC}'; WPD_DEVICE_TYPE_PID = 15;

My problem is that I'm having isses figuring out how to retrieve the information.

I was expecting that IPortableDevice would have a .Property procedure just like IPortableDeviceContent, but it doesn't.

However, IPortableDeviceManager does have a procedure called GetDeviceProperty.

I have sample code which can get the friendly name of a WPD device (from the unit PortableDeviceApiLib_TLB.pas).

Code:

function GetDeviceFriendlyName(sDeviceId: WideString): WideString;
  var iDevNameLen: LongWord;
      iRes: Integer;
      s: WideString;
begin
  //get length of friendly name:
  iDevNameLen := 0;
  s := '';

  iRes := My_IPortableDeviceManager.GetDeviceFriendlyName(PWideChar(sDeviceId),  Word(nil^),  iDevNameLen);

  if iRes = S_OK then
    if iDevNameLen>0 then
    begin
      SetLength(s, iDevNameLen);
      ZeroMemory(PWideChar(s), iDevNameLen);
      iRes := My_IPortableDevice.GetDeviceFriendlyName(PWideChar(sDeviceId),  PWord(PWideChar(s))^,  iDevNameLen);
      s := Trim(s);
    end;

  result := s;
end;

My test code for getting a property of a device looks as following (basically the same... almost...):

function GetDeviceProperty(ADeviceID, APropertyName: WideString): WideString;
  var iDevPropLen: LongWord;
      iRes: Integer;
      s: WideString;
      t: cardinal;
begin
  //get length of property name:
  iDevPropLen := 0;
  s := '';

  iRes := My_IPortableDeviceManager.GetDeviceProperty(PWideChar(ADeviceID), PWideChar(APropertyName), Byte(nil^), iDevPropLen, t);
  showmessage(inttostr(ires)+#13#10+inttostr(iDevPropLen)+#13#10+inttostr(t));
  //just trying to get some useful information…
end;

According to this MSDN article, pDatashould be set to NULL and pcbData set to zero in order to get the size of pcbData.

Which I am doing.

Could someone help explaining what I need to do in order to get it right?

EDIT: I found this code which seems to be in python, that gets the device type.

I'm trying to port it to delphi.

Aid Vllasaliu
  • 85
  • 2
  • 11
  • Please show the declaration of your interface, and please tell us the value of `iRes`. Also, `iRes` is not an `Integer`. It is an `HRESULT`. – David Heffernan Mar 19 '15 at 12:33
  • @DavidHeffernan Could you elaborate what you mean with "declaration of instance"? I don't quite understand. iRes = -2147024894. Oh, I see that now, thanks. – Aid Vllasaliu Mar 19 '15 at 12:37
  • I edited the question. See edit at bottom. – Aid Vllasaliu Mar 19 '15 at 12:40
  • I think what you're looking for is `IPortableDeviceCapabilities`, not `IPortableDeviceManager`. https://msdn.microsoft.com/en-us/library/windows/desktop/dd319362%28v=vs.85%29.aspx The former exposes the method `GetFunctionalCategories` which returns the device's capabilities (image capture, audio capture, storage, etc). https://msdn.microsoft.com/en-us/library/windows/desktop/dd319367%28v=vs.85%29.aspx – J... Mar 20 '15 at 12:43
  • @J... I've looked in to that. An external hard drive has one functional category which is (taken from my test app) `Dev. Functional Categories Count: 1. Dev. Functional Category: WPD_FUNCTIONAL_CATEGORY_STORAGE`, and so does my iPhone – Aid Vllasaliu Mar 20 '15 at 23:52
  • @AidVllasaliu ...so what's the problem? As far as the system is concerned, an iPhone is just a storage device. You can't use it for image capture (like a webcam), or as a media device (like a DLNA server), or for audio capture (like a USB microphone)... unless you have drivers that present it to the operating system as such? – J... Mar 21 '15 at 00:52
  • @J... I was expecting that the iPhone was going to be recognized as a phone. which it isn't. – Aid Vllasaliu Mar 21 '15 at 12:32
  • @AidVllasaliu I don't think there is a "phone" category in WPD... one of the possible supported features is SMS, but I expect you would need a device driver for the iPhone that exposed this feature. I don't know if Apple supplies such a driver. It's not clear what you expect to be able to do or what you are attempting to accomplish. – J... Mar 21 '15 at 13:25
  • @J... incorrect. there is a "phone" category. Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/dd389048%28v=vs.85%29.aspx – Aid Vllasaliu Mar 21 '15 at 13:45
  • I meant for device capabilities - you can identify the device as a phone, but you can't use it as a phone. The only things you can do with a device are enumerated in its capabilities. – J... Mar 21 '15 at 14:17

2 Answers2

0

Your HRESULT is $80070002. That's a COM error code that wraps the Win32 error code, ERROR_FILE_NOT_FOUND. And that means that either the device ID or property name are incorrect. Assuming that you have indeed got the correct device ID, the obvious conclusion is that you are attempting to read the value of a property that does not exist.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • high probability. according to https://msdn.microsoft.com/en-us/library/windows/desktop/dd389048%28v=vs.85%29.aspx, theres a note at the bottom saying `Note WPD applications must use the capabilities of the portable device to determine functionally, not the WPD_DEVICE_TYPES value.` – Aid Vllasaliu Mar 19 '15 at 12:44
  • Did I misunderstand the question? Were you interested in understanding the error? – David Heffernan Mar 20 '15 at 12:18
  • I think you misunderstood the question, maybe I wasn't clear enough. I'd like to determine the device type. is it a phone? is it a camera? what kind of device is it? – Aid Vllasaliu Mar 20 '15 at 16:59
  • Absolutely not. Nobody needs to spoonfeed me, all I'm asking for is help. I'm having a hard time understanding how determine the WPD device type. I've supplied the resources I find most useful, including code. Code can stay untouched, all I need is to understand how to determine the WPD device type. Does not need to be by code, can also be by a good explanation. – Aid Vllasaliu Mar 20 '15 at 17:35
  • We did this once before. You say that, but your actions belied that. – David Heffernan Mar 20 '15 at 17:41
  • I also posted my answer eventually when I figured it out. Which I will do in this case as well, as I have figured it out now. Thanks for your help. – Aid Vllasaliu Mar 20 '15 at 18:36
  • Only you are answering a different question from us. We answer the question you ask. You answer an unasked question that we can't see and with details we don't have. It's not what this site is about. – David Heffernan Mar 20 '15 at 18:42
  • Absolutely not, I asked and specified that I need to determine the device type of a WPD device, I provided my attempts in terms of code, as well as providing relevant documentation. I was lost in the djungle of the WPD API and could not figure it out myself (which I eventually did), hence asking for help. I also provided code in a different language which apparently does what I need, I successfully ported the code, and am willing to share it with the world. Now tell me how I'm answering a different question and how I have not provided sufficient details. – Aid Vllasaliu Mar 21 '15 at 00:02
  • I don't think your argument is valid, David. Sometimes a question might not be properly elaborated due to lack of knowledge, and being able to come to a place like SO to ask something and getting constructive feedback is great. Please don't insult me by making me seem like I'm lazy by saying `I guess you won't be happy until somebody produces all the code you need` and then continuing by saying `We did this once before. You say that, but your actions belied that`. If you can not help or feel like the problem is poorly elaborated, make that statement, no need to get personal. No one is perfect. – Aid Vllasaliu Mar 21 '15 at 00:07
  • No. I thought the question you asked was clear. I thought you wanted to know why your code failed and how to fix it. – David Heffernan Mar 21 '15 at 05:55
  • I guess I need to be more clear in the future. Sorry for the confusion. Please just don't insult me in the future, I can't appreciate that. – Aid Vllasaliu Mar 22 '15 at 09:53
  • I don't think I did. I must say I have found your response to a couple of questions to be ungrateful. – David Heffernan Mar 22 '15 at 11:41
  • I'm not ungrateful, I said that no one needs to write code for me, I'm happy with documentation and code references as well. – Aid Vllasaliu Mar 22 '15 at 11:49
  • I see it differently from you. I think we just have to leave it there. I respect your point of view. – David Heffernan Mar 22 '15 at 11:54
  • I guess so. At the end of the day, we're here for the same reason. – Aid Vllasaliu Mar 22 '15 at 12:05
  • I'm not sure we are. I'm here to answer the questions that are asked. You seem to expect answers to unasked questions with complete solutions to your own problems, much of which is visible only to you. I respect your opinion, but I vehemently disagree with it. – David Heffernan Mar 22 '15 at 12:10
  • As far as I'm concerned I'm the only one posting complete solutions after a lot of trial and error. You haven't helped me a bit with my issue. – Aid Vllasaliu Mar 22 '15 at 12:17
  • There it is. The confusion between the question you ask and the problem you face – David Heffernan Mar 22 '15 at 12:55
  • Again, that's the issue. This isn't about solving your problem. That's not how SO works. – David Heffernan Mar 22 '15 at 13:07
  • Is it specifically me or do you mean that SO isn't about solving problems? – Aid Vllasaliu Mar 22 '15 at 13:18
  • No, it's not you. But SO is about answering the specific question that was asked. – David Heffernan Mar 22 '15 at 13:48
  • Never mind, I've seen your comments before on other peoples posts, and you've been acting the same towards them. I guess that's just the way you are, attacking peoples persona instead of doing something useful. – Aid Vllasaliu Mar 22 '15 at 13:49
  • Now you are being personal and insulting. I'm not attacking you. I think you don't see the difference between you problem and your question. They are not the same. I've said my peace. – David Heffernan Mar 22 '15 at 14:03
  • Oh I'm insulting you now? Oh yeah, I remember, I'm also that lazy guy that won't be happy until somebody produces all the code I need. I've said mine several times as well. Thank you for your time, David. – Aid Vllasaliu Mar 22 '15 at 14:51
  • You misunderstand. I never suggested you were lazy. Just that your expectations were unrealistic. – David Heffernan Mar 22 '15 at 14:55
-2

Ok, so eventually I figured out how to read the device type of a device.

What needed to be done was to read the device properties.

Some very interesting information could be read, such as the battery level of the device, if available.

EDIT: I used the source found here as a reference to WPD programming.

Code tested with external harddrives, SD memory card reader, USB sticks, Apple iPhone, and Samsung Galaxy phone.

Code is available HERE!!!

Just copy and paste the code in to a new VCL project, add a listbox called DeviceList, a memo called LogMemo, a panel called Panel1, and a button inside Panel1 called Button1. Then doubleclick on the Listbox, and doubleclick on the button, and finally doubleclick on the main form, and everything should run flawlsessly.

Programmed in Delphi XE7.

Aid Vllasaliu
  • 85
  • 2
  • 11
  • David, I've produced the code for you. Feel free to use it! – Aid Vllasaliu Mar 22 '15 at 11:29
  • This doesn't answer the question that was asked, and presents no code. Off site links are not valuable, especially ones that contain PDFs and not selectable text. -1 – David Heffernan Mar 22 '15 at 11:56
  • Offsite code was needed, since only 30 thousand characters are allowed in the body. My code contains somewhere near 60 thousand characters. I had no choice. – Aid Vllasaliu Mar 22 '15 at 12:06
  • And the document can be downloaded as its original `.TXT` format. – Aid Vllasaliu Mar 22 '15 at 12:08
  • And it does answer my question, both as the property-reading and the wpd device type retreival. – Aid Vllasaliu Mar 22 '15 at 12:08
  • You had a choice. You could have answered the question that was asked with a small amount of code. I think, as I've said to you before, you are mixing up answer the question that was asked, with solving the greater problem that you face. – David Heffernan Mar 22 '15 at 12:10
  • The Small amount of code that you are refering to is not available in the any of Delphis stock units. Actually, the code in the document I posted is completely Bare Bone, I had to sit for well over an hour to strip down the 3+ units that contained the original code which I found online. Now tell me I how I had a choice. – Aid Vllasaliu Mar 22 '15 at 12:13
  • Stop insulting my dedication David. – Aid Vllasaliu Mar 22 '15 at 12:14
  • I'm not insulting you. I disagree with the way you approach questions. I'm sure you can respect my right to have an opinion that differs from yours. – David Heffernan Mar 22 '15 at 12:17
  • I can respect your opinion, but you don't contribute with any constructive critique, David. You claim I'm expecting fairtail code, served on a silver plate, ready to be copy and pasted. You `-1`my question AND my answer when I've spent several **DAYS** on my issue solving my problem. You claim my answer isn't answering my question. You claim all these things. Why? How come I come back with complete code that satisfies my own need for an answer? It is because I solved my problem, which I asked in the question, which I posted in the answer. If you don't want to contribute, please stay out. – Aid Vllasaliu Mar 22 '15 at 12:21
  • In order to be an answer here, it must be self-sustaining, which means *all relevant content* must be here, in the answer itself. If the off-site link you've used for the *entire* relevant content is not available for some reason (moved, off-line, deleted, etc.), the post has zero value to future readers and therefore doesn't belong here. The [help] has information about how to properly answer questions here. If they're not suitable for you, feel free to ask for help elsewhere. (In addition, the site you've used requires a *paid trial subscription* in order to obtain the code. Useless here.) – Ken White Aug 24 '17 at 14:53