The processing that occurs in the callback function is entirely up to you. This section illustrates a simple way of handling it.
UserData buffer
In this example, the UserData buffer is a structure with a field whose value points to the actual message buffer. Other fields keep track of the message buffer's contents as it is filled:
typedef struct ORCA_UserDataInfo { LPBYTE lpszBuffer; // Buffer to store data DWORD dwCallCount; // # of messages in buffer DWORD dwBufferSize; // size of buffer DWORD dwBufferOffset; // current offset in buffer } ORCA_USERDATAINFO, FAR *PORCA_USERDATAINFO;
Calling program
In the calling program, the UserDataInfo structure is initialized.
The calling program does not know how much room will be required for messages, so it allocates 60000 bytes (an arbitrary size). If you are gathering link errors, it's probably enough. It might not be enough if you wanted directory information for a large library:
ORCA_USERDATAINFO UserDataBuffer; PORCA_USERDATAINFO lpUserDataBuffer; lpUserDataBuffer = &UserDataBuffer; lpUserDataBuffer->dwCallCount = 0; lpUserDataBuffer->dwBufferOffset = 0; lpUserDataBuffer->dwBufferSize = 60000; lpUserDataBuffer->lpszBuffer = (LPTSTR)malloc((size_t)lpUserDataBuffer-> dwBufferSize); memset(lpUserDataBuffer->lpszBuffer, 0x00,(size_t)lpUserDataBuffer->dwBufferSize);
Define function pointer
The calling program defines a function pointer to the callback function that it passes to the ORCA function:
PBORCA_LINKPROC fpLinkProc; fpLinkProc = (PBORCA_LINKPROC)LinkErrors;
Call ORCA
The calling program calls the ORCA function, passing the callback function pointer and the UserData buffer pointer. This example calls PBORCA_ExecutableCreate, whose callback type is PBORCA_LNKPROC:
rtn = PBORCA_ExecutableCreate(..., (PBORCA_LNKPROC) fpLinkProc, lpUserDataBuffer);
Process results
Finally, the calling program can process or display information that the callback function stored in the UserData buffer.
Free allocated memory
If your UserData structure allocates memory, free the allocated memory:
free( lpUserDataBuffer->lpszBuffer )
Callback program
The callback program receives a structure with the current error or information and stores the information in the message buffer pointed to by lpszBuffer in the UserData buffer. It also manages the pointers stored in the UserData buffer.
Simple callback
A simple callback might do the following:
-
Keep count of the number of times it is called
-
Store messages and reallocate buffer if it overflows
This code implements a callback called LinkErrors for PBORCA_ExecutableCreate:
void CALLBACK LinkErrors(PPBORCA_LINKERR lpLinkError, LPVOID lpUserData) { PORCA_USERDATAINFO lpData; LPBYTE lpCurrByte; LPTSTR lpCurrentPtr; int iNeededSize; lpData = (PORCA_USERDATAINFO) lpUserData; // Keep track of number of link errors lpData->dwCallCount++; // Is buffer already full? if (lpData->dwBufferOffset==lpData->dwBufferSize) return; // How long is the new message? // Message length plus carriage rtn and newline iNeededSize = (_tcslen(lpLinkError->lpszMessageText) + 2)* sizeof(TCHAR); // Reallocate buffer if necessary if ((lpData->dwBufferOffset + iNeededSize) > lpData->dwBufferSize) { LPVOID lpNewBlock; DWORD dwNewSize; dwNewSize = lpData->dwBufferSize * 2; lpNewBlock = realloc(lpData->lpszBuffer, (size_t)dwNewSize); if (lpNewBlock) { lpData->lpszBuffer = (LPTSTR) lpNewBlock; lpData->dwBufferSize = dwNewSize; } else return; } // Set pointer for copying message to buffer lpCurrentPtr = lpData->lpszBuffer + lpData->dwBufferOffset; lpCurrString = (LPTSTR) lpCurrByte; // Copy link error message, CR, and LF to buffer. _tcscpy(lpCurrentPtr, lpLinkError->lpszMessageText); _tcscat(lpCurrentPtr, _TEXT("\r\n")); lpData->dwBufferOffset += iNeededSize; return; }