(I accidentally only sent this message to Rob only)
Hi,
To get away from the tests stuff I thought I'd resurrect my plans to implement EnumServiceStatusExW (the A-version is needed by SysInternal's Process Explorer amongst others).
I have most of the stuff ready:
- Added svcctl_EnumServicesStatusExW to /wine/wine-git/include/wine/svcctl.idl - Added svcctl_EnumServicesStatusExW to /wine/wine-git/programs/services/rpc.c - Added a enumeration routine to /wine/wine-git/programs/services/services.c (and .h of course) - Changed EnumServiceStatusExW in /wine/wine-git/dll/advapi32/service.c to call svcctl_EnumServicesStatusExW
There is one important thing I can't get my head around.
The call to EnumServicesStatusExW passes a pointer to a BYTE * lpServices with a length of cBufSize.
lpServices is an array of some ENUM_SERVICE_STATUS_PROCESSW structs. The first two parameters of these structs are pointers to WCHAR strings. The strings for all these structs (on Windows) can be found after all the structs themselves. So imagine that we should have 2 services in our lpServices to be passed back to the initial caller:
0000 [0].lpServiceName -> 0088 0008 [0].lpDisplayName -> 0114 0016 [0].SERVICE_STATUS struct of 7 DWORDS 0044 [1].lpServiceName -> 0140 0052 [1].lpDisplayName -> 0166 0060 [1].SERVICE_STATUS struct of 7 DWORDS 0088 "ServiceName1" 0114 "DisplayName1" 0140 "ServiceName1' 0166 "DisplayName1"
(The above is what EnumServicesStatusExW would pass back to the caller)
The enumeration I have in services.c fills the lpServiceName pointer to the actual string. Likewise for lpDisplayName. This is all in the RPC world (where the lpServices address is different to the caller passed address). When lpServices is passed back to the caller I can see that the SERVICE_STATUS structs are correct but the pointers to the strings are pointing to the original ones.
How can I make sure the pointers to the strings are correctly passed back as well? Should the RPC stuff take care of these pointers and 'translate' them?
We could of course teach EnumServicesStatusExW to change the pointers to the appropriate ones. We know exactly where there strings are so it should be fairly trivial to change those pointers. This however seems like a hack.
Any idea is welcome.
From: Paul Vriens [mailto:paul.vriens.wine@gmail.com]
How can I make sure the pointers to the strings are correctly passed back as well? Should the RPC stuff take care of these pointers and 'translate' them?
Those pointers are not really pointers but byte offsets from the start of the buffer. It's been a long time that I have looked into this but I believe that this is even the case on the client side (e.g. the caller). So there should be no problem with this, as RPC simply would need to copy the entire buffer including the strings section.
We could of course teach EnumServicesStatusExW to change the pointers to the appropriate ones. We know exactly where there strings are so it should be fairly trivial to change those pointers. This however seems like a hack.
Well the original MS service control API has separate RPC calls for the A and W calls and the offsets are therefore calculated by the service control service itself correctly. If you want to implement the A call on top of the W call as is currently done for the other servicecontrol APIs too, you will probably have to adjust those offsets accordingly in the W to A translation of the strings.
In the interest of a really compatible RPC interface to the MS service control service however, it would be better to implement the separate RPC calls for the A and W version.
Currently an MS Window client trying to call the Wine service control service over RPC will fail for the A calls (but there are also other RPC problems that make Windows-Wine RPC not work well).
Rolf Kalbermatter
Rolf Kalbermatter wrote:
From: Paul Vriens [mailto:paul.vriens.wine@gmail.com]
How can I make sure the pointers to the strings are correctly passed back as well? Should the RPC stuff take care of these pointers and 'translate' them?
Those pointers are not really pointers but byte offsets from the start of the buffer. It's been a long time that I have looked into this but I believe that this is even the case on the client side (e.g. the caller). So there should be no problem with this, as RPC simply would need to copy the entire buffer including the strings section.
Sure, RPC does return the structs and the strings but the pointers (byte offsets) are wrong. How can I teach RPC to respect (change) those pointers?
We could of course teach EnumServicesStatusExW to change the pointers to the appropriate ones. We know exactly where there strings are so it should be fairly trivial to change those pointers. This however seems like a hack.
Well the original MS service control API has separate RPC calls for the A and W calls and the offsets are therefore calculated by the service control service itself correctly. If you want to implement the A call on top of the W call as is currently done for the other servicecontrol APIs too, you will probably have to adjust those offsets accordingly in the W to A translation of the strings.
Yeah, I know. I have the thing working with this (and that mentioned hack) but I'm obviously looking for the best (read correct) solution.
In the interest of a really compatible RPC interface to the MS service control service however, it would be better to implement the separate RPC calls for the A and W version.
Currently an MS Window client trying to call the Wine service control service over RPC will fail for the A calls (but there are also other RPC problems that make Windows-Wine RPC not work well).
More things to fix then ;)