![]() |
#1 |
Senior Member
Join Date: Mar 2006
Location: Dallas
Posts: 462
|
Error from CoInitializeSecurity (WMI)
I borrowed the System plugin calls that F0rt wrote about and wrote my own program to access WMI. On my laptop at home (Vista 64) it works fine, and here at work (XP Pro) it works fine. But on our target systems (Win 2000 Pro) the very first system call fails.
I stripped the program down to some essentials, and it still fails. The routines (in the attached file) work on my XP desktop and fail with RPC_E_TOO_LATE (0x80010119) at the very first line of code. On other Win2k machines here, that call works but it fails later with a line that says failed ExecQuery 0xc0000005. Is there anyone that can see why this fails (either error, or best, both errors)? thanks, Don |
![]() |
![]() |
![]() |
#2 |
Moderator
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,504
|
first one just means CoInitializeSecurity has already been called (this function is process wide and only works once) Maybe some kind of injected shell extension or something on the failing machines?
as far as the other one goes, what does WBEMTest.exe do on the failing machine? as a final note, getting logical drives can be done without using WMI IntOp $PostCount $PostCount + 1 |
![]() |
![]() |
![]() |
#3 |
Senior Member
Join Date: Mar 2006
Location: Dallas
Posts: 462
|
When it doesn't fail on the ole32::CoInitializeSecurity, it makes it through the next 2 calls OK (ole32::CoCreateInstance, IWbemLocator->ConnectServer) but gets a 0xC0000005 returned by the call on line 92 to IWbemServices->ExecQuery. The program doesn't terminate, but I guess it means to COM-connected process terminated. I don't try to use the other value (a IEnumWbemClassObject) that it ought to return.
I'm home now, so I can't try any experiments or investigate the injected shell extension theory until tomorrow. About other ways to get logical drives - are you suggesting there is an API for it? I want to find the logical drives, and for each one I want to know if it is a CD or removable drive, what size it is, and the current volume name (if there is media in it). Don |
![]() |
![]() |
![]() |
#4 |
Moderator
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,504
|
if WBEMTest.exe works where IWbemServices->ExecQuery called by system.dll fails, there could be a bug in the COM handling or using wrong parameter somewhere. If it also fails with WBEMTest.exe, I'm guessing there is a problem with the COM default security on that machine
As far as native API goes, call GetLogicalDriveStrings() or GetDriveType() directly in a loop. GetVolumeInformation() gives you label, GetDiskFreeSpace[Ex]() the size. It should also be noted that a volume could be mounted in a subfolder somewhere and not have a dos style drive letter at all, for those, call FindFirstVolume+FindFirstVolumeMountPoint and friends IIRC IntOp $PostCount $PostCount + 1 |
![]() |
![]() |
![]() |
#5 |
Senior Member
Join Date: Mar 2006
Location: Dallas
Posts: 462
|
I misunderstood your earlier question asking what WBEMTEST.exe does on the failing machine. It works properly, I get successful data back from all the queries I'm using.
|
![]() |
![]() |
![]() |
#6 |
Senior Member
Join Date: Mar 2006
Location: Dallas
Posts: 462
|
Thought I found a solution, but it still crashes
I read the MSDN article on Getting WMI Data from the Local Computer and saw a note that says on Win2000 you have to specify the default authentication credentials for a user by using a SOLE_AUTHENTICATION_LIST structure in the pAuthList parameter of CoInitializeSecurity .
I've tried to do that but my program crashes now on the call to CoInitializeSecurity. I know this isn't really a NSIS problem at this point, but hope that Anders, F0rt or someone can spot what I've done wrong. Here's the part that sets up the call to CoInitializeSecurity. I have tried it with and without the SOLE_AUTHENTICATION_SERVICE structure, it crashes either way. It runs fine on XP and Vista. TIAcode: Don |
![]() |
![]() |
![]() |
#7 |
Moderator
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,504
|
Your code looks correct to me.
Would it be possible for you to write a little app in C to test so we could rule out the system plugin? or alternatively debug WBEMTEST.exe and check the parameters it passes to CoInitializeSecurity (Also, using comments like that in a plugin parameter might not be so smart, not sure if the script parser is able to handle it) edit: (this is on XP, not sure if wbemtest is the same on 2000) code: RPC_C_AUTHN_LEVEL_DEFAULT might equal RPC_C_AUTHN_LEVEL_NONE on a local machine, I don't know (And its documented that you need to pass those extra structs on 2k, so I'm sure its not going to fix it) IntOp $PostCount $PostCount + 1 Last edited by Anders; 14th October 2009 at 21:39. |
![]() |
![]() |
![]() |
#8 |
Senior Member
Join Date: Mar 2006
Location: Dallas
Posts: 462
|
Thanks for the suggestions. You're right, the script parser does not like the comments embedded in the SYSTEM plugin call strings. I took those out after I spotted that.
I have pretty much duplicated (in NSIS code) the example MSDN showed, it runs on XP but only gets as far as the IWbemServices::ExecQuery call on Win2000. That call doesn't crash the app, but returns a 0xC0000005 error code. The latest code is attached to this post. I will look at trying to run the debugger on WbemTest.exe. Here is the call to CoInitializeSecurity that seems to work on both OS's. code: Don |
![]() |
![]() |
![]() |
#9 |
Moderator
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,504
|
the WBEMTEST.exe version on windows 2000 does not have CoInitializeSecurity in its import table (it could still be calling it, but it is a bit weird to just not import it normally)
edit: So it does end up calling CoInitializeSecurity after GetProcAddress'ing it (why, I don't know, that function should exist on every version of windows so there is no point in delay loading it) IntOp $PostCount $PostCount + 1 Last edited by Anders; 18th October 2009 at 02:03. |
![]() |
![]() |
![]() |
#10 |
Moderator
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,504
|
looking over your code some more, you are using "w" as the arguments in some places, those arguments are really BSTR's and BSTR != plain unicode string, you can use a BSTR where a unicode string is expected, but not the other way around and the system plugin does not have a BSTR parameter type AFAIK, you can make a proper BSTR with the SysAllocString() function
IntOp $PostCount $PostCount + 1 |
![]() |
![]() |
![]() |
#11 |
Moderator
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,504
|
I made a little test app in c++, it works fine on XP but fails with WBEM_E_INVALID_CLASS (0x80041010) on IWbemServices->ExecQuery()
Not really sure where to go from here IntOp $PostCount $PostCount + 1 |
![]() |
![]() |
![]() |
#12 |
Moderator
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,504
|
Right, got it working now!
For whatever crazy reason, using CLSID_WbemAdministrativeLocator in the call to CoCreateInstance seems to fix things on 2000 (plain CLSID_WbemLocator works fine on XP) I'll end with a few notes...
IntOp $PostCount $PostCount + 1 |
![]() |
![]() |
![]() |
#13 |
Senior Member
Join Date: Mar 2006
Location: Dallas
Posts: 462
|
Anders, thanks for continuing work on my problem, and the suggestion that CLSID_WbemAdministrativeLocator might work for me on Win2000.
After a little playing around, I've got it working! I switched to CLSID_WbemAdministrativeLocator and commented out the CoSetProxyBlanket. The SerialNumber came back different (even though here at home I run Win2000 under VirtualBox), but that is accurate (according to what WBEMTest shows. Then I tried a different query (Select * from Win32Bios) and property ('Name'), and after crashing the WMI repository a few times, it comes back with the BIOS name correctly. Hopefully the crash is just an artifact of the VirtualBox. XP continues to work correctly. [A few minutes go by] Now I've incorporated those changes into my WMI.nsh, and my app runs in XP and Win2000! Thank you, Anders! I'll need to clean up WMI.nsh, but I plan to put it in the wiki when I've done that. I'm in the middle of moving to a new apartment and may not be able to try on a true Win2000 system until either Monday or Tuesday. Don |
![]() |
![]() |
![]() |
#14 |
Moderator
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,504
|
As far as crashes go, one thing you should fix is the w vs BSTR problem.
code like System::Call "$3->20(w 'WQL', w 'Select * from Win32_BIOS' ... is wrong, like I said, you can't use w, you need proper BSTR's (you can fake BSTR's with the system plugin struct syntax (on BSTR's you are going to free yourself) something like *{i 3,w "abc"}i.r0 but the pointer you must pass is not $0 but $0+4 (length is at -4) ) IntOp $PostCount $PostCount + 1 |
![]() |
![]() |
![]() |
#15 | |
Moderator
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,504
|
A very delayed update here.
Quote:
Neither CoInitializeSecurity nor CoSetProxyBlanket exist on 95RTM but that does not explain why 2000 delay loads CoInitializeSecurity. I can also confirm that CoSetProxyBlanket on the svc interface can be used instead of CoInitializeSecurity, even on 2000 (Not that it matters in NSIS). IntOp $PostCount $PostCount + 1 |
|
![]() |
![]() |
![]() |
|
Thread Tools | Search this Thread |
Display Modes | |
|
|