Re: Whats the correct way to pass a D array type to a win32 api function wanting a buffer?

2017-07-13 Thread John Chapman via Digitalmars-d-learn

On Thursday, 13 July 2017 at 01:15:46 UTC, FoxyBrown wrote:

ENUM_SERVICE_STATUS_PROCESS[5000] services;
	auto res = SVC.EnumServicesStatusExA(schSCManager, 
SC_ENUM_TYPE.SC_ENUM_PROCESS_INFO, servicesType, 
SERVICE_STATE_ALL, cast(ubyte*)services.ptr, 
5000*ENUM_SERVICE_STATUS_PROCESS.sizeof, &dwBytesNeeded, 
&dwCount, &resume, cast(const(char)*)null);


You need to call EnumServicesStatusEx twice - the first time to 
get the required size of the buffer. See the docs for the 
lpServices parameter here 
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682640(v=vs.85).aspx


Then allocate a buffer using the returned dwBytesNeeded and call 
the function again with your buffer and its size.


Re: Whats the correct way to pass a D array type to a win32 api function wanting a buffer?

2017-07-12 Thread Adam D. Ruppe via Digitalmars-d-learn

On Thursday, 13 July 2017 at 01:15:46 UTC, FoxyBrown wrote:

auto EnumServices()


I wouldn't use auto here. The reason you get mismatch types on 
return here since you don't return consistent types inside.




ENUM_SERVICE_STATUS_PROCESS[5000] services;


Are you sure you are getting the same A vs W version there? You 
explicitly call the A version of the function, but do not specify 
it here.



auto s = services[i].lpServiceName;
writeln(*s);


Like the other user above said, you should be treating that like 
a C string anyway. Use printf or fromStringz or slice it 
yourself... just make sure you tend to char vs wchar like above.



return services;


That's kinda hideous, returning the entire buffer by value. I do 
NOT recommend you attempt to slice and dup though, since the 
win32 function uses space at the end of the buffer to store the 
strings referenced by the structs.


Ideally, you'd avoid returning this thing at all and just use it 
locally. Perhaps pass a callback function/delegate that takes 
each item as you iterate through.


Re: Whats the correct way to pass a D array type to a win32 api function wanting a buffer?

2017-07-12 Thread Nicholas Wilson via Digitalmars-d-learn

On Thursday, 13 July 2017 at 01:15:46 UTC, FoxyBrown wrote:
Everything I do results in some problem, I've tried malloc but 
then converting the strings resulted in my program becoming 
corrupted.



Heres the code:

auto EnumServices()
{

auto schSCManager = OpenSCManager(null, null, 
SC_MANAGER_ALL_ACCESS);

if (NULL == schSCManager)
{
print("OpenSCManager failed (%d)\n", GetLastError());
return null; // Why can't we return a null? Surely we 
don't have to cast a null in to a typeof null?

}

import core.stdc.stdlib;

DWORD dwBytesNeeded, dwCount, lpResumeHandle, resume;

	auto servicesType = (SERVICE_DRIVER | 
SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER | 
SERVICE_WIN32 | SERVICE_WIN32_OWN_PROCESS | 
SERVICE_WIN32_SHARE_PROCESS);




ENUM_SERVICE_STATUS_PROCESS[5000] services;
	auto res = SVC.EnumServicesStatusExA(schSCManager, 
SC_ENUM_TYPE.SC_ENUM_PROCESS_INFO, servicesType, 
SERVICE_STATE_ALL, cast(ubyte*)services.ptr, 
5000*ENUM_SERVICE_STATUS_PROCESS.sizeof, &dwBytesNeeded, 
&dwCount, &resume, cast(const(char)*)null);



for(int i = 0; i < dwCount; i++)
{
auto s = services[i].lpServiceName;
writeln(*s);
}


return services;
}


What is the signature of the function you are trying to call? 
(make sure its correct :))

Allocating 5000 services may blow your stack.
you can just use `services.sizeof` instead of 
`5000*ENUM_SERVICE_STATUS_PROCESS.sizeof`.
You are returning that massive static array, remember that static 
arrays are value types in D so that will get copied. Consider 
allocating the array and returning a slice of it.


Note also that `lpServiceName` is probably a `char*` so 
drefferencing will give you a char, not a string. Use 
std.string.fromStringz(?) for that.


Whats the correct way to pass a D array type to a win32 api function wanting a buffer?

2017-07-12 Thread FoxyBrown via Digitalmars-d-learn
Everything I do results in some problem, I've tried malloc but 
then converting the strings resulted in my program becoming 
corrupted.



Heres the code:

auto EnumServices()
{

auto schSCManager = OpenSCManager(null, null, 
SC_MANAGER_ALL_ACCESS);

if (NULL == schSCManager)
{
print("OpenSCManager failed (%d)\n", GetLastError());
return null; // Why can't we return a null? Surely we 
don't have to cast a null in to a typeof null?

}

import core.stdc.stdlib;

DWORD dwBytesNeeded, dwCount, lpResumeHandle, resume;

	auto servicesType = (SERVICE_DRIVER | SERVICE_FILE_SYSTEM_DRIVER 
| SERVICE_KERNEL_DRIVER | SERVICE_WIN32 | 
SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS);




ENUM_SERVICE_STATUS_PROCESS[5000] services;
	auto res = SVC.EnumServicesStatusExA(schSCManager, 
SC_ENUM_TYPE.SC_ENUM_PROCESS_INFO, servicesType, 
SERVICE_STATE_ALL, cast(ubyte*)services.ptr, 
5000*ENUM_SERVICE_STATUS_PROCESS.sizeof, &dwBytesNeeded, 
&dwCount, &resume, cast(const(char)*)null);



for(int i = 0; i < dwCount; i++)
{
auto s = services[i].lpServiceName;
writeln(*s);
}


return services;
}