I need to call hllapi function of pcshll32.dll using delphi. It's works with personal communications of ibm. How can i change the code bellow to delphi ? Thanks !!!
The EHLLAPI entry point (hllapi) is always called with the following four parameters:
EHLLAPI Function Number (input)
Data Buffer (input/output)
Buffer Length (input/output)
Presentation Space Position (input); Return Code (output)
The prototype for IBM Standard EHLLAPI is:
[long hllapi (LPWORD, LPSTR, LPWORD, LPWORD);
The prototype for IBM Enhanced EHLLAPI is:
[long hllapi (LPINT, LPSTR, LPINT, LPINT);
Each parameter is passed by reference not by value. Thus each parameter to the function call must be a pointer to the value, not the value itself. For example, the following is a correct example of calling the EHLLAPI Query Session Status function:
#include "hapi_c.h"
struct HLDQuerySessionStatus QueryData;
int Func, Len, Rc;
long Rc;
memset(QueryData, 0, sizeof(QueryData)); // Init buffer
QueryData.qsst_shortname = ©A©; // Session to query
Func = HA_QUERY_SESSION_STATUS; // Function number
Len = sizeof(QueryData); // Len of buffer
Rc = 0; // Unused on input
hllapi(&Func, (char *)&QueryData, &Len, &Rc); // Call EHLLAPI
if (Rc != 0) { // Check return code
// ...Error handling
}
All the parameters in the hllapi call are pointers and the return code of the EHLLAPI function is returned in the value of the 4th parameter, not as the value of the function.
You need to convert hapi_c.h to Delphi first (if you have never done that before you might want to start reading here: Rudy's Delphi Corner: Pitfalls of Converting
Related
I've created an After Effects script that extracts data from JSON files downloaded from an HTTPS URL. The problem is with the C++ DLL I've coded to download it and pass it back to the script. Even though it has been working fine, there was one instance of memory leak - After Effects issued a popup saying, "STRING MEMORY LEAK".
I'm new to C++ but I've managed to compose a DLL that downloads the files based on the examples provided with the After Effects installation (samplelib and basicexternalobject) as well as by Microsoft's C++ documentation. The Adobe JavaScript Tools Guide says that the method "ESFreeMem()" must be "called to free memory allocated for a null-terminated string passed to or from library functions". The problem is I don't know how or where to use it. I'm using After Effects CC 15.0.0 (build 180) on Windows 7.
This is the C++ function that gets some parameters from the javascript caller and returns a string with the JSON contents. If it fails it returns a bool (FALSE) so that the script can do what is necessary in this case.
extern "C" TvgAfx_Com_API long DownloadJson(TaggedData* argv, long argc, TaggedData * result)
{
//... first I check the arguments passed
// The returned value type
result->type = kTypeString;
//Converts from string into LPCWSTR ---------------------------------------------------
std::wstring stemp = s2ws(argv[0].data.string);
LPCWSTR jsonLink = stemp.c_str();
std::wstring stemp02 = s2ws(argv[1].data.string);
LPCWSTR jsonHeader = stemp02.c_str();
//--------------------------------------------------------------------------------------
//Class that does the HTTP request
WinHttpClient client(jsonLink, jsonHeader);
//Synchronous request
if (client.SendHttpsRequest())
{
string httpResponse = client.GetHttpResponse();
if (httpResponse.length() > 0)
{
//Sends response string back to javascript
result->data.string = getNewBuffer(httpResponse);
}
else
{
//Sends FALSE back to javascript
result->type = kTypeBool;
result->data.intval = 0;
}
}
else
{
//Sends FALSE back to javascript
result->type = kTypeBool;
result->data.intval = 0;
}
return kESErrOK;
}
The class WinHttpClient that does the actual request frees the memory allocated to the buffer that holds the response. Here's a piece of code:
// Read the data.
ZeroMemory(pszOutBuffer, dwSize + 1);
if (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded))
{
//Log error
}
else
{
resource.append(pszOutBuffer).c_str();
}
// Free the memory allocated to the buffer.
delete[] pszOutBuffer;
This is the function that the Adobe example uses to hold the string that will be returned to javascript:
//brief Utility function to handle strings and memory clean up
static char* getNewBuffer(string& s)
{
// Dynamically allocate memory buffer to hold the string
// to pass back to JavaScript
char* buff = new char[1 + s.length()];
memset(buff, 0, s.length() + 1);
strcpy(buff, s.c_str());
return buff;
}
Now, the manual says this method must be implemented:
/**
* \brief Free any string memory which has been returned as function result.
* JavaScipt calls this function to release the memory associated with the string.
* Used for the direct interface.
*
* \param *p Pointer to the string
*/
extern "C" SAMPLIB void ESFreeMem (void* p)
{
if (p)
free (p);
}
What I understand from this is that the memory associated with the json string returned must be released. But didn't the request class already do it? I just don't know where to call this method and what to pass on to it. I would appreciate any help. Thanks a lot!
When you create a DLL ExternalObject for After Effects, it's really just an interface that you call via some ExtendScript script. You have to load the ExternalObject in the AE Script and once loaded, the methods / functions you create in the C++ class can be called from the script.
You have to know how to load the DLL in an ExtendScript script file. Then, you can call the methods of the DLL.
I have a Win32 C++ dll (A) that calls another Win32 C++ dll (B). (B) is loaded using LoadLibrary and contains a method:
Draw(HDC hDC, LPRECT lpRect, LPBUFFER buffer, LPOPTIONS options)
Buffer structure is defined as:
struct Buffer
{
char* pData;
long Length;
TCHAR FileName[MAX_PATH];
Extension Extension;
};
typedef Buffer BUFFER, *LPBUFFER;
(A) fills BUFFER with filename, length etc and calls the Draw function. The Draw function then uses the values from BUFFER. It all works fine when DLLs are compiled as 64-bit but if I compile them as 32-bit then I start getting garbage values in BUFFER fields in (B). Logs shows that the values are good in (A) but turn into garbage when they reach (B).
I tried changing the Structure Alignment Option /ZpX and calling convention for Draw method (__cdecl, __stdcall) but none helped. I think it is related to calling convention because if I change Draw function syntax and put BUFFER as first param then (B) gets correct values. What's going on here?
Function pointer type:
typedef bool (__cdecl *DrawFunc)(HDC hDC, LPRECT lpRect, LPBUFFER buffer, LPOPTIONS options);
Then in InitInstance:
pDrawFunc = (DrawFunc)GetProcAddress(dllHandle, "Draw");
UPDATE
1. As mentioned above, if I put BUFFER as first param then it receives correct values.
2. HDC being a single numeric value always receives correct value
3. RECT gets incorrect values, very large ones
I believe the problem has something to do with structs. Only structs get incorrect values.
UPDATE 2
OK I found out my own silly mistake, the declaration for Draw method had LPRECT whereas the implementation had RECT. My bad, sorry about that.
But I am still not sure why:
1. Other parameters were showing garbage values?
2. Why it worked in 64-bit?
Ok, I create a solution with 3 projects: library B, that contains Draw(), library A, that has Test(), that loads library B and call Draw() with some Buffer* and application test, that links with library A and calls Test(). Everything works fine, both for 32 bit and 64. Small snippet of Test():
#include "stdafx.h"
#include "A.h"
#include "../B/B.h"
namespace {
LPBUFFER CreateBuffer(const char* const data, LPCTSTR const name)
{
if(!data || !name)
return NULL;
LPBUFFER buffer = new BUFFER();
buffer->Length = static_cast<long>(strlen(data) + 1);
buffer->pData = new char[buffer->Length];
strcpy_s(buffer->pData, buffer->Length * sizeof(char), data);
buffer->Extension = 0;
::ZeroMemory(buffer->FileName, _countof(buffer->FileName) * sizeof(TCHAR));
_tcscpy_s(buffer->FileName, name);
return buffer;
}
void DestroyBuffer(LPBUFFER buffer)
{
delete [] buffer->pData;
buffer->Length = 0;
buffer->pData = NULL;
buffer->Extension = 0;
::ZeroMemory(buffer->FileName, _countof(buffer->FileName) * sizeof(TCHAR));
delete buffer;
}
} // namespace
A_API void Test()
{
HMODULE b_lib = ::LoadLibrary(_T("B.dll"));
if(!b_lib)
{
::OutputDebugString(_T("Can't load library\n"));
return;
}
typedef bool (*DrawFunction)(HDC hDC, LPRECT lpRect, LPBUFFER buffer, LPOPTIONS options);
DrawFunction draw = reinterpret_cast<DrawFunction>(::GetProcAddress(b_lib, "Draw"));
if(!draw)
{
::OutputDebugString(_T("Can't get address of Draw()"));
goto FINISH_LABEL;
}
LPBUFFER buffer = CreateBuffer("test", _T("path"));
draw(NULL, NULL, buffer, NULL);
DestroyBuffer(buffer);
FINISH_LABEL:
::FreeLibrary(b_lib);
b_lib = NULL;
}
And a whole solution: https://www.dropbox.com/s/5ei6ros9e8s94e2/B.zip
I am trying to write a CLI wrapper around some low-level COM-related calls. One of the operations that I need to do specifically is to get a specific value from a PROPVARIANT, i.e.:
pwszPropName = varPropNames.calpwstr.pElems[dwPropIndex];
where pwszPropName is documented to be an LPWSTR type and dwPropIndex is a DWORD value passed into the function by the user.
I have a native function defined as follows:
HRESULT CMetadataEditor::GetPropertyNameByID(DWORD ID, wchar_t *PropertyName)
I would like to return the value of pwszPropName via *PropertyName.
Is the wchar_t* type the best way to do this, and would I need to pin *PropertyName in my CLI to ensure it does not move in memory? Do I need to define the length of *PropertyName before passing it to native code (buffer)?
If wchar_t* is the right variable type to pass into the native function, what is the proper conversion of LPWSTR to whar_t*, and how then would you convert that value to System::String?
I have tried a number of different techniques over the past few days and can't seem to get anything right.
------------UPDATE------------
Here is my full code. First, the CLI:
String^ MetadataEditor::GetPropertyNameByID(unsigned int ID)
{
LPWSTR mPropertyName = L"String from CLI";
m_pCEditor->GetPropertyNameByID(ID, mPropertyName);
//Convert return back to System::String
String^ CLIString = gcnew String(mPropertyName);
return CLIString;
}
And the native code:
HRESULT CMetadataEditor::GetPropertyNameByID(DWORD ID, LPWSTR PropertyName)
{
HRESULT hr = S_OK;
LPWSTR myPropName;
PROPVARIANT varNames;
PropVariantInit(&varNames);
hr = m_pMetadata->GetAllPropertyNames(&varNames);
if(hr != S_OK)
{
PropVariantClear(&varNames);
return hr;
}
myPropName = varNames.calpwstr.pElems[ID];
PropertyName = myPropName;
PropVariantClear(&varNames);
return hr;
}
It doesn't seem like the value (myPropName) is set properly and/or sustained back into the CLI function because the CLI returns the value I set on mPropertyName before calling the native function.. I'm not sure why or how to fix this.
UPDATE!!!!
I suspected my problem had something to do with variables going out of scope. So I changed the C++ function definition as follows:
LPWSTR GetPropertyNameByID(DWORD ID, HRESULT ErrorCode);
After adjusting the CLI as well, I now get a value returned, but the first character is incorrect, and in fact can be different with every call. I tried using ZeroMemory() in the native class before assigning the output of the PROPVARIANT to the variable (ZeroMemory(&myPropName, sizeof(myPropName +1)); but still no luck.
You can design unmanaged function by the following way:
HRESULT CMetadataEditor::GetPropertyNameByID(DWORD ID, LPWSTR PropertyName, size_t size)
{
....
wcscpy(PropertyName, varNames.calpwstr.pElems[ID]); // or wcsncpy
...
}
PropertyName is the buffer allocated by caller, size is its size. Inside the function wcscpy or wcsncpy the string varNames.calpwstr.pElems[ID] to PropertyName. Client code:
WCHAR mPropertyName[100];
m_pCEditor->GetPropertyNameByID(ID, mPropertyName, sizeof(mPropertyName)/sizeof(mPropertyName[0]));
Think, for example, how GetComputerName API is implemented, and do the same
I have a WiFi Listener registered as a callback (pointer function) with a fixed 3rd party interface. I used a static member of my function to register the callback function and then that static function calls a nonstatic member through a static cast. The main problem is that I cannot touch the resulting char * buff with any members of my class nor can I even change an int flag that is also a member of my class. All result in runtime access violations. What can I do? Please see some of my code below. Other problems are described after the code.
void *pt2Object;
TextWiFiCommunication::TextWiFiCommunication()
{
networkDeviceListen.rawCallback = ReceiveMessage_thunkB;
/* some other initializing */
}
int TextWiFiCommunication::ReceiveMessage_thunkB(int eventType, NETWORK_DEVICE *networkDevice)
{
if (eventType == TCP_CLIENT_DATA_READY)
static_cast<TextWiFiCommunication *>(pt2Object)->ReceiveMessageB(eventType,networkDevice);
return 1;
}
int TextWiFiCommunication::ReceiveMessageB(int eventType, NETWORK_DEVICE *networkDevice)
{
unsigned char outputBuffer[8];
// function from an API that reads the WiFi socket for incoming data
TCP_readData(networkDevice, (char *)outputBuffer, 0, 8);
std::string tempString((char *)outputBuffer);
tempString.erase(tempString.size()-8,8); //funny thing happens the outputBuffer is double in size and have no idea why
if (tempString.compare("facereco") == 0)
cmdflag = 1;
return 1;
}
So I can't change the variable cmdflag without an access violation during runtime. I can't declare outputBuffer as a class member because nothing gets written to it so I have to do it within the function. I can't copy the outputBuffer to a string type member of my class. The debugger shows me strlen.asm code. No idea why. How can I get around this? I seem to be imprisoned in this function ReceiveMessageB.
Thanks in advance!
Some other bizzare issues include: Even though I call a buffer size of 8. When I take outputBuffer and initialize a string with it, the string has a size of 16.
You are likely getting an access violation because p2tObject does not point to a valid object but to garbage. When is p2tObject initialized? To what does it point?
For this to work, your code should look something like this:
...
TextWifiCommunication twc;
p2tObject = reinterpret_cast<void*>(&twc);
...
Regarding the string error, TCP_readData is not likely to null-terminate the character array you give it. A C-string ends at the first '\0' (null) character. When you convert the C-string to a std::string, the std::string copies bytes from the C-string pointer until it finds the null terminator. In your case, it happens to find it after 16 characters.
To read up to 8 character from a TCP byte stream, the buffer should be 9 characters long and all the bytes of the buffer should be initialized to '\0':
...
unsigned char outputBuffer[9] = { 0 };
// function from an API that reads the WiFi socket for incoming data
TCP_readData(networkDevice, (char *)outputBuffer, 0, 8);
std::string tempString((char *)outputBuffer);
...
I was trying to hook a custom recv() winsock2.0 method to a remote process, so that my function executes instead of the one in the process, i have been googling this and i found some really good example, but they lack description
typedef (WINAPI * WSAREC)( SOCKET s, char *buf, int len, int flags ) = recv;
Now my question is, what does this mean, or does, is this some sort of a pointer to the real recv() function?
And then the other piece of code for the custom function
int WINAPI Cus_Recv( SOCKET s, char *buf, int len, int flags )
{
printf("Intercepted a packet");
return WSAREC( s, buf, len, flags ); // <- What is this?
}
Sorry if these questions sound really basic, i only started learning 2 or 3 weeks ago.
Thanks.
where did you find such an example ?
the first line tries to define a new type WSAREC, which is a pointer to a function having the same signature as recv(). unfortunately, it is also trying to declare a variable of this type to store the address of the recv() function. the typedef is wrong since the function is lacking a return type. so it does not compile under Visual Studio 2003.
you may have more luck using:
int (WINAPI * WSAREC)( SOCKET s, char *buf, int len, int flags ) = &recv;
which declares only a variable of type "pointer to function", which stores the address of the recv().
now the second snippet is a function which has the same signature as the recv()function, which prints a message, then calls the original recv() through the function pointer declared above.
the code here only shows how to call a function through a pointer: it does not replace anything in the current process.
also, i am not sure you can interfere with another process and replace one function at your will. it would be a great threat to the security of the system. but why would you do that in the first place ??