The following code is pretty screwed up, even though it doesn't look like it. I have a buf, a simple malloc which hold the results of a win32 call. I am then trying to copy over the data in buf to a D struct.

But when copying the strings, the buf location changes, screwing up the copying process. It shouldn't happen, buf never changes value anywhere except the first malloc(which is once). Somehow it is getting changed, but where?

The specific win32 or style is irrelevant, I am talking either about a bug or some subtle D thing because the code makes sense. (Fill Buf, iterate through buffer copying over to D values).

I've ran in to this before, D does something fishy and it wastes hours upon hours trying to track done some stupid little thing it does.

The buf value changes when calling cstr2dstr but I've had it with other values to(any function call such as to!string, etc seems to trigger it).




struct ServiceData
{
    wstring Name;
    wstring LongName;
    int Type;
    int State;
    int ControlsAccepted;
    int Win32ExitCode;
    int SpecificExitCode;
    int CheckPoint;
    int WaitHint;
    int ProcessId;
    int Flags;
}

auto cstr2dstr(wchar* cstr)
{
        import std.array;
        auto str = appender!wstring;
        auto len = lstrlen(cstr);
        str.reserve(len);
        
        for(int i = 0; i < len; i++)
                str.put(cstr[i]);

        return str.data;
}


auto EnumServices()
{
        import core.stdc.stdlib, std.traits;
        ServiceData[] servicesList;

auto buf = malloc(50000); // Gets changed later, even though never an assignment
        auto buf2 = buf; // does not change
auto schSCManager = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS);
    if (NULL == schSCManager)
    {
        print("OpenSCManager failed (%d)\n", GetLastError());
        return servicesList;
    }
                
        DWORD dwBytesNeeded, dwCount, lpResumeHandle, resume, totalCount;
auto servicesType = (SERVICE_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER | SERVICE_WIN32 | SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS);

        int cnt = 0;            
        auto res = 0;
        do
    {
// Manually copy over data, this is because EnumSErvicesStatus adds data at end of array for some odd ball reason making it difficult to build the correct array sequentially
                for(int i = 0; i < dwCount; i++)
                {
                        ENUM_SERVICE_STATUS_PROCESSW x;
                        ServiceData d;
auto s = cast(ENUM_SERVICE_STATUS_PROCESSW*)(buf + i*ENUM_SERVICE_STATUS_PROCESSW.sizeof);
//                    before buf is of correct value
                        d.Name = cstr2dstr(s.lpServiceName);
// after buf is invalid, yet buf is never assigned

                }

                
res = EnumServicesStatusExW(schSCManager, SC_ENUM_TYPE.SC_ENUM_PROCESS_INFO, servicesType, SERVICE_STATE_ALL, cast(ubyte*)buf, 50000, &dwBytesNeeded, &dwCount, &resume, cast(const(char)*)null); if (ERROR_MORE_DATA != GetLastError()) { print("Error enumerating services."); break; }
        } while (res == 0);

        
        for(int i = 0; i < totalCount; i++)
        {
                auto s = servicesList[i];
writeln(s.Name, " - ", s.LongName, " - ", s.Type, " = ", s.State);
        }


        return servicesList;
}

Reply via email to