k.. not for dummies, but it makes life much easier (+ you can choose between FILEMAP & SHELL modes.. [filemap is available in next beta])
#include <ioFTPD.h>
/*
Prototypes of some undocumented winapi functions
HANDLE WINAPI SHAllocShared(LPVOID Buf, ULONG BufSize, DWORD PID);
BOOL WINAPI SHFreeShared(HANDLE hMemory, DWORD PID);
LPVOID WINAPI SHLockShared(HANDLE hMemory, DWORD PID);
BOOL WINAPI SHUnlockShared(LPVOID Buf);
*/
typedef struct _LOCALDATA
{
HWND hDaemon;
DWORD dwProcessId;
DWORD dwType;
HMODULE hShellLibrary;
HANDLE hHeap;
LPVOID ShellAlloc;
LPVOID ShellLock;
LPVOID ShellUnlock;
LPVOID ShellFree;
} LOCALDATA, * LPLOCALDATA;
typedef struct _ALLOCATION
{
LPDC_MESSAGE lpMessage;
LPVOID lpMemory;
LPVOID hDaemon;
HANDLE hObject;
HANDLE hEvent;
DWORD dwBytes;
} ALLOCATION, * LPALLOCATION;
BOOL InitializeLocalData(LPLOCALDATA lpData, DWORD dwType)
{
// Initialize data structure
lpData->dwProcessId = GetCurrentProcessId();
lpData->dwType = dwType;
lpData->hDaemon = FindWindow("ioFTPD::MessageWindow", NULL);
lpData->hHeap = GetProcessHeap();
if (dwType == SHELL)
{
// Load shell library
lpData->hShellLibrary = LoadLibrary("shell32.dll");
if (lpData->hShellLibrary)
{
lpData->ShellAlloc = GetProcAddress(lpData->hShellLibrary, "SHAllocShared");
lpData->ShellFree = GetProcAddress(lpData->hShellLibrary, "SHFreeShared");
lpData->ShellUnlock = GetProcAddress(lpData->hShellLibrary, "SHUnlockShared");
lpData->ShellFree = GetProcAddress(lpData->hShellLibrary, "SHLockShared");
}
else return FALSE;
}
else lpData->hShellLibrary = NULL;
return (lpData->hDaemon ? TRUE : FALSE);
}
VOID DeleteLocalData(LPLOCALDATA lpData)
{
if (lpData->hShellLibrary) FreeLibrary(lpData->hShellLibrary);
lpData->dwType = (DWORD)-1;
}
LPALLOCATION SharedAllocate(BOOL bCreateEvent, DWORD dwBytes, LPLOCALDATA lpData)
{
LPALLOCATION lpAllocation;
LPDC_MESSAGE lpMessage;
DWORD dwMessage;
HANDLE hObject, hEvent;
LPVOID hRemote;
BOOL bError;
bError = TRUE;
hEvent = NULL;
hObject = NULL;
lpMessage = NULL;
if (! dwBytes) return FALSE;
if (bCreateEvent &&
! (hEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) return NULL;
lpAllocation = (LPALLOCATION)HeapAlloc(lpData->hHeap, 0, sizeof(ALLOCATION));
if (! lpAllocation)
{
if (hEvent) CloseHandle(hEvent);
return NULL;
}
dwBytes += sizeof(DC_MESSAGE);
// Allocate memory for local process
switch (lpData->dwType)
{
case SHELL:
hObject = ((HANDLE (WINAPI *)(LPVOID, ULONG, DWORD))lpData->ShellAlloc)(NULL, dwBytes, lpData->dwProcessId);
if (hObject) lpMessage = (LPDC_MESSAGE)((LPVOID (WINAPI *)(HANDLE, DWORD))lpData->ShellLock)(hObject, lpData->dwProcessId);
dwMessage = WM_DATACOPY_SHELLALLOC;
break;
case FILEMAP:
hObject = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE|SEC_COMMIT, 0, dwBytes, NULL);
if (hObject) lpMessage = (LPDC_MESSAGE)MapViewOfFile(hObject, FILE_MAP_WRITE|FILE_MAP_READ, 0, 0, dwBytes);
dwMessage = WM_DATACOPY_FILEMAP;
break;
}
if (lpMessage)
{
lpMessage->hEvent = hEvent;
lpMessage->lpContext = &lpMessage[1];
lpMessage->lpMemoryBase = (LPVOID)lpMessage;
lpMessage->dwIdentifier = 0;
// Query ioftpd
SetLastError(0);
hRemote = (LPVOID)SendMessage(lpData->hDaemon, dwMessage, (WPARAM)lpData->dwProcessId, (LPARAM)hObject);
if (hRemote && GetLastError() == NO_ERROR) bError = FALSE;
}
if (bError)
{
// Free resources
switch (lpData->dwType)
{
case SHELL:
if (lpMessage) ((BOOL (WINAPI *)(LPVOID))lpData->ShellUnlock)((LPVOID *)lpMessage);
if (hObject) ((BOOL (WINAPI *)(HANDLE, DWORD))lpData->ShellFree)(hObject, lpData->dwProcessId);
hObject = NULL;
break;
case FILEMAP:
if (lpMessage) UnmapViewOfFile(lpMessage);
break;
}
if (hObject && hObject != INVALID_HANDLE_VALUE) CloseHandle(hObject);
if (hEvent) CloseHandle(hEvent);
HeapFree(lpData->hHeap, 0, lpAllocation);
lpAllocation = NULL;
}
else
{
// Update structure
lpAllocation->hDaemon = hRemote;
lpAllocation->lpMemory = &lpMessage[1];
lpAllocation->hEvent = hEvent;
lpAllocation->hObject = hObject;
lpAllocation->lpMessage = lpMessage;
lpAllocation->dwBytes = dwBytes - sizeof(DC_MESSAGE);
}
return lpAllocation;
}
VOID SharedFree(LPALLOCATION lpAllocation, LPLOCALDATA lpData)
{
// Free resources
switch (lpData->dwType)
{
case SHELL:
((BOOL (WINAPI *)(LPVOID))lpData->ShellUnlock)((LPVOID *)lpAllocation->lpMessage);
((BOOL (WINAPI *)(HANDLE, DWORD))lpData->ShellFree)(lpAllocation->hObject, lpData->dwProcessId);
lpAllocation->hObject = NULL;
break;
case FILEMAP:
UnmapViewOfFile(lpAllocation->lpMessage);
break;
}
if (lpAllocation->hEvent) CloseHandle(lpAllocation->hEvent);
if (lpAllocation->hObject) CloseHandle(lpAllocation->hObject);
SendMessage(lpData->hDaemon, WM_DATACOPY_FREE, 0, (LPARAM)lpAllocation->hDaemon);
HeapFree(lpData->hHeap, 0, lpAllocation);
}
DWORD QueryDaemon(DWORD dwQueryType, LPALLOCATION lpAllocation, DWORD dwTimeOut, LPLOCALDATA lpData)
{
lpAllocation->lpMessage->dwIdentifier = dwQueryType;
PostMessage(lpData->hDaemon, WM_SHMEM, 0, (LPARAM)lpAllocation->hDaemon);
if (dwTimeOut &&
lpAllocation->hEvent)
{
if (WaitForSingleObject(lpAllocation->hEvent, dwTimeOut) == WAIT_TIMEOUT) return (DWORD)-1;
return lpAllocation->lpMessage->dwReturn;
}
// No timeout/event, return value can't be checked
return (DWORD)-1;
}
/*
Main() - Everything is stuffed here
*/
INT main(INT ArgC, CHAR *ArgV[])
{
LPALLOCATION lpAllocation;
LPDC_ONLINEDATA lpOnlineData;
LOCALDATA LocalData;
DWORD dwStartTicks, dwStopTicks, dwUsers;
BOOL bLoop;
bLoop = TRUE;
dwStartTicks = GetTickCount();
dwUsers = 0;
if (InitializeLocalData(&LocalData, FILEMAP))
{
// Allocate memory
lpAllocation = SharedAllocate(TRUE, sizeof(DC_ONLINEDATA) + _MAX_PATH * 2, &LocalData);
if (lpAllocation)
{
lpOnlineData = (LPDC_ONLINEDATA)lpAllocation->lpMemory;
// Init structure
lpOnlineData->iOffset = 0;
lpOnlineData->dwSharedMemorySize = lpAllocation->dwBytes;
for (;bLoop
{
// Send message to daemon
switch (QueryDaemon(DC_GET_ONLINEDATA, lpAllocation, 5000, &LocalData))
{
case (DWORD)-1:
// End/time out/fatal error
bLoop = FALSE;
break;
default:
// Need more memory
lpOnlineData->iOffset++;
break;
case 0:
// Success
if (! lpOnlineData->OnlineData.szRealPath) lpOnlineData->OnlineData.szRealPath = "";
printf("%i: %s\n",
lpOnlineData->OnlineData.Uid, lpOnlineData->OnlineData.szRealPath);
dwUsers++;
}
}
// Free memory
SharedFree(lpAllocation, &LocalData);
}
DeleteLocalData(&LocalData);
}
// Get system tickcount
dwStopTicks = GetTickCount();
// Output process duration
printf("Time wasted: %.3fseconds (%u ticks, %u users)\n",
(dwStopTicks - dwStartTicks) /1000., dwStopTicks - dwStartTicks, dwUsers);
Sleep(10000);
return FALSE;
}