PDA

View Full Version : [c] DataCopy functions for dummies


darkone
10-29-2003, 04:04 AM
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;
}

darkone
10-29-2003, 04:08 AM
Press quote, if you want tabbed versions version of functions.

ADDiCT
10-29-2003, 08:09 AM
This is probably another stupid question of me, but where are WM_DATACOPY_SHELLALLOC, WM_DATACOPY_FREE, SHELL and FILEMAP defined?
I can't find it in any of the header files (i also tried upgrading my includes to the versions of the latest (unregged) ioFTPD rar-sfx, but then i even got more errors :p)

FTPServerTools
10-30-2003, 04:06 AM
Hmm filemapping is indeed easy too... Tho due to compatibility issues I'd prefer shmem. But now I gotta scream: VERSION NUMBER pleeeeeaaaaase.
Its needed for scripters.

darkone
10-30-2003, 04:21 AM
I really suggest moving to memory mapping: it seems faster + it's more reliable (shell allocation routines seem to return weird errors, in some cases)

Mouton
10-30-2003, 09:52 AM
When we'll have the reply to ADDiCT'S question, we'll be able to compile something. Untill then, we'll have to stick with shmem.

SnypeTEST
10-30-2003, 10:06 AM
oooh memory mapping will be much better :) then I can use it with pb :D

darkone
10-30-2003, 12:55 PM
you won't be able to use it until next version anyways.. so just define them as something & expect next version of headers to define them for you

Harm
11-09-2003, 09:50 AM
Something i've just noticed:


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");
}


should be


if (lpData->hShellLibrary)
{
lpData->ShellAlloc = GetProcAddress(lpData->hShellLibrary, "SHAllocShared");
lpData->ShellFree = GetProcAddress(lpData->hShellLibrary, "SHFreeShared");
lpData->ShellUnlock = GetProcAddress(lpData->hShellLibrary, "SHUnlockShared");
lpData->ShellLock = GetProcAddress(lpData->hShellLibrary, "SHLockShared");
}

darkone
11-11-2003, 12:06 AM
True..