I'm having trouble getting libsndfile-1.dll to work in my MSVC project. I can load the library and retrieve the version string from the dll by calling sf_command() from my code. However, I can't seem to get sf__open() to return a SNDFILE pointer.
I've also noticed that I can't get fopen() to return a FILE pointer either (maybe this is related, I think sf_open() uses fopen()!?).
I'm pretty new to MSVC, C/C++ and windows in general so I'm probably missing something really obvious.
My main.cpp looks like this:
#include <windows.h>
#include <stdio.h>
#include "sndfile.hh"
// create some function pointers to point to the dll function addresses
// I'm winging this a bit. hopefully it's right!? seems to work!
typedef int (*SF_COMMAND)(SNDFILE*, int, void*, int);
typedef SNDFILE* (*SF_OPEN)(const char*, int, SF_INFO*);
int main()
{
// dll handle
HINSTANCE hDLL = NULL;
// create some vars to store the dll funcs in
SF_COMMAND sf_command;
SF_OPEN sf_open;
// load the dll
hDLL = LoadLibrary(L"libsndfile-1.dll");
// check the dll loaded
if( NULL == hDLL )
{
printf("Error, Could not load library \n");
return 1;
}
// get the dll funcs
sf_command = (SF_COMMAND)GetProcAddress(hDLL, "sf_command");
sf_open = (SF_OPEN)GetProcAddress(hDLL, "sf_open");
// check we got the funcs
if(!(sf_command && sf_open)){
printf("Error exporting dll functions \n");
return 2;
}
// all good so far!
// try the first function
char* version_string[sizeof(char*)*4];
int res = sf_command(NULL, SFC_GET_LIB_VERSION, &version_string, sizeof(version_string));
if(res){
// all good!
printf("Version: %s \n", version_string);
}
// now try and create a SNDFILE pointer
SF_INFO info;
SNDFILE* sfp = sf_open("c:\\Godspeed.aif", SFM_READ, &info);
if(sfp){
printf("Hurray! successfully opened the SNDFILE!! \n");
}else{
printf("Doh! couldn't open the SNDFILE!! \n");
// Grr!!
return 3;
}
return 0;
}
The project builds and exits with code 3 (couldn't open the file! (I'm pretty sure the file is there!!)).
When I run the exe the output is:
Version: libsndfile-1.0.17
Doh! couldn't open the SNDFILE
Does anyone have any suggestions as to where I'm going wrong?
Many thanks,
Josh.
Hmm, I really should learn not to post to forums late at night!
I had another attempt this morning and had the file open within minutes.
I was getting my paths all wrong (not used to these weird windows paths)!
I tried using a relative path and bingo!
Hope that helps someone!
Related
I was taking a look at this Github project: https://github.com/LloydLabs/delete-self-poc
This project uses the SetFileInformationByHandle API (https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfileinformationbyhandle) in a somewhat creative way to allow the deletion from disk of a locked file. I am attempting to implement this as part of a larger program, however I have ran into an issue when compiling for x86. I use mingw-w64 on a debian machine to compile my program and when doing compatibility checks for x86, I found a very strange issue.
#include "main.h"
static
HANDLE
ds_open_handle(
PWCHAR pwPath
)
{
return CreateFileW(pwPath, DELETE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
}
static
BOOL
ds_rename_handle(
HANDLE hHandle
)
{
FILE_RENAME_INFO fRename;
RtlSecureZeroMemory(&fRename, sizeof(fRename));
// set our FileNameLength and FileName to DS_STREAM_RENAME
LPWSTR lpwStream = DS_STREAM_RENAME;
fRename.FileNameLength = sizeof(lpwStream);
RtlCopyMemory(fRename.FileName, lpwStream, sizeof(lpwStream));
return SetFileInformationByHandle(hHandle, FileRenameInfo, &fRename, sizeof(fRename) + sizeof(lpwStream));
}
static
BOOL
ds_deposite_handle(
HANDLE hHandle
)
{
// set FILE_DISPOSITION_INFO::DeleteFile to TRUE
FILE_DISPOSITION_INFO fDelete;
RtlSecureZeroMemory(&fDelete, sizeof(fDelete));
fDelete.DeleteFile = TRUE;
return SetFileInformationByHandle(hHandle, FileDispositionInfo, &fDelete, sizeof(fDelete));
}
int
main(
int argc,
char** argv
)
{
WCHAR wcPath[MAX_PATH + 1];
RtlSecureZeroMemory(wcPath, sizeof(wcPath));
// get the path to the current running process ctx
if (GetModuleFileNameW(NULL, wcPath, MAX_PATH) == 0)
{
DS_DEBUG_LOG(L"failed to get the current module handle");
return 0;
}
HANDLE hCurrent = ds_open_handle(wcPath);
if (hCurrent == INVALID_HANDLE_VALUE)
{
DS_DEBUG_LOG(L"failed to acquire handle to current running process");
return 0;
}
// rename the associated HANDLE's file name
DS_DEBUG_LOG(L"attempting to rename file name");
if (!ds_rename_handle(hCurrent))
{
DS_DEBUG_LOG(L"failed to rename to stream");
return 0;
}
DS_DEBUG_LOG(L"successfully renamed file primary :$DATA ADS to specified stream, closing initial handle");
CloseHandle(hCurrent);
// open another handle, trigger deletion on close
hCurrent = ds_open_handle(wcPath);
if (hCurrent == INVALID_HANDLE_VALUE)
{
DS_DEBUG_LOG(L"failed to reopen current module");
return 0;
}
if (!ds_deposite_handle(hCurrent))
{
DS_DEBUG_LOG(L"failed to set delete deposition");
return 0;
}
// trigger the deletion deposition on hCurrent
DS_DEBUG_LOG(L"closing handle to trigger deletion deposition");
CloseHandle(hCurrent);
// verify we've been deleted
if (PathFileExistsW(wcPath))
{
DS_DEBUG_LOG(L"failed to delete copy, file still exists");
return 0;
}
DS_DEBUG_LOG(L"successfully deleted self from disk");
return 1;
}
When compiling the base code found in the linked repository (and shown above) as x86, attempting to run the program fails at the SetFileInformationByHandle call in the ds_rename_handle function. Calling GetLastError() returns 123:
ERROR_INVALID_NAME
123 (0x7B)
The filename, directory name, or volume label syntax is incorrect.
The very bizarre part is that the program succeeds when ran from an Administrator prompt. Even stranger, compiling the same code for x64 works both in a normal and an Administrator prompt.
As a sanity check I copied the code verbatim over to VS2019 and compiled there, and the resulting x86 program was able to run without Administrator privileges.
The only changes to the source code made on the debian system were made in the header file:
#pragma once
#pragma comment(lib, "Shlwapi.lib")
#include <Windows.h>
#include <shlwapi.h>
#include <stdio.h>
#include <stdlib.h>
#define DS_STREAM_RENAME L":wtfbbq"
#define DS_DEBUG_LOG(msg) wprintf(L"[LOG] - %s\n", msg)
Where <Windows.h> was changed to <windows.h> and the DS_DEBUG_LOG line changed to %ls so that the entire log message would print.
The GCC command used to compile for x86 was:
i686-w64-mingw32-gcc main.c -o delete32.exe -s -DUNICODE -Os -lshlwapi
I have tried removing all switches and compiling and it still fails.
As a note, the shlwapi library is only required for the very last call in main(), PathFileExistsW. I have commented out that portion and removed shlwapi from imports and from the gcc command to no effect.
The x64 gcc command which succeeded was:
x86_64-w64-mingw32-gcc main.c -o delete32.exe -s -DUNICODE -Os -lshlwapi
In the issues tab of the github repo there are some mentions of errors in the code which I have looked at separately. However I would desperately like to know why mingw is causing an issue with the 32 bit version of this program. Unfortunately "just compile with VS" isn't an option, as I use a program to generate and compile the program that this bit of code will be part of on my linux machine.
Thanks for any insight.
RtlCopyMemory(fRename.FileName, lpwStream, sizeof(lpwStream)); writes 4 or 8 bytes into a 2 byte buffer! Who knows where the remaining bytes are going, the program behavior is probably undefined.
The concept of deleting a running exe like this might work but the code indicates that the author does not have a full understanding of Windows and C. You are better off rewriting it from scratch...
Edit:
After playing with your uploaded files I can with confidence say that it is the lack of a application manifest that causes it to fail when it is not elevated. Your vc file has a requestedExecutionLevel element which gives it Vista operating system context. If you remove the manifest resource in the vc exe it stops working. If you add a manifest to the mingw exe it starts working.
the ds_rename_handle function is wrong implemented.
the FILE_RENAME_INFO is variable size structure.
as result declaration
FILE_RENAME_INFO fRename;
almost always wrong (it will ok only if FileName containing 1 or 2 symbols)
really we need first calculate FileNameLength and then allocate PFILE_RENAME_INFO based on this
as example:
ULONG FileNameLength = (ULONG)wcslen(DS_STREAM_RENAME) * sizeof(WCHAR);
ULONG dwBufferSize = FIELD_OFFSET(FILE_RENAME_INFO, FileName) + FileNameLength;
PFILE_RENAME_INFORMATION fRename = (PFILE_RENAME_INFORMATION)alloca(dwBufferSize);
so complete code for ds_rename_handle can be next:
ULONG ds_rename_handle(HANDLE hHandle, PCWSTR DS_STREAM_RENAME)
{
ULONG FileNameLength = (ULONG)wcslen(DS_STREAM_RENAME) * sizeof(WCHAR);
ULONG dwBufferSize = FIELD_OFFSET(FILE_RENAME_INFO, FileName) + FileNameLength;
PFILE_RENAME_INFO fRename = (PFILE_RENAME_INFO)alloca(dwBufferSize);
fRename->ReplaceIfExists = TRUE;
fRename->RootDirectory = 0;
fRename->FileNameLength = FileNameLength;
memcpy(fRename->FileName, DS_STREAM_RENAME, FileNameLength);
return SetFileInformationByHandle(hHandle, FileRenameInfo,
fRename, dwBufferSize) ? NOERROR : GetLastError();
}
but documentation of FILE_RENAME_INFO is very bad. unclear - in what form - full pathname, file name or a relative pathname - must be FileName ?!
from my research - it must be full pathname only (not file name) or begin with a colon : ( The new name for the stream )
much more better use NtSetInformationFile with FileRenameInformation
compare description of FILE_RENAME_INFORMATION structure with FILE_RENAME_INFO !
here exist detailed description - in what form FileName it should be.
so i always use
NTSTATUS ds_rename_handle_nt(HANDLE hHandle, PCWSTR DS_STREAM_RENAME)
{
ULONG FileNameLength = (ULONG)wcslen(DS_STREAM_RENAME) * sizeof(WCHAR);
ULONG dwBufferSize = FIELD_OFFSET(FILE_RENAME_INFO, FileName) + FileNameLength;
PFILE_RENAME_INFORMATION fRename = (PFILE_RENAME_INFORMATION)alloca(dwBufferSize);
fRename->ReplaceIfExists = TRUE;
fRename->RootDirectory = 0;
fRename->FileNameLength = FileNameLength;
memcpy(fRename->FileName, DS_STREAM_RENAME, FileNameLength);
IO_STATUS_BLOCK iosb;
return NtSetInformationFile(
hHandle, &iosb, fRename, dwBufferSize, FileRenameInformation);
}
I am trying to write a small extension for PostgreSQL.
As a way to test if my module loads correctly I am writing some stuff in files in the void _PG_init(void) and void _PG_fini(void) functions. Here is the code of these two functions:
#include "postgres.h"
#include "executor\executor.h"
#include "fmgr.h"
#include "funcapi.h"
#include <stdio.h>
PG_MODULE_MAGIC;
extern void _PG_init(void);
extern void _PG_fini(void);
static void myExecutorStart(QueryDesc *queryDesc, int eflags);
static void myExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count);
static void myExecutorFinish(QueryDesc *queryDesc);
static void myExecutorEnd(QueryDesc *queryDesc);
static ExecutorStart_hook_type prevExecutorStart = NULL;
static ExecutorRun_hook_type prevExecutorRun = NULL;
static ExecutorFinish_hook_type prevExecutorFinish = NULL;
static ExecutorEnd_hook_type prevExecutorEnd = NULL;
void _PG_init(void) {
FILE *file = NULL;
file = fopen("F:\\init.txt", "a+");
fprintf(file, "Init started!\n");
fclose(file);
prevExecutorStart = ExecutorStart_hook;
ExecutorStart_hook = myExecutorStart;
prevExecutorRun = ExecutorRun_hook;
ExecutorRun_hook = myExecutorRun;
prevExecutorFinish = ExecutorFinish_hook;
ExecutorFinish_hook = myExecutorFinish;
prevExecutorEnd = ExecutorEnd_hook;
ExecutorEnd_hook = myExecutorEnd;
}
void _PG_fini(void) {
FILE *file = NULL;
file = fopen("F:\\fini.txt", "a+");
fprintf(file, "Fini started!\n");
fclose(file);
ExecutorStart_hook = prevExecutorStart;
ExecutorRun_hook = prevExecutorRun;
ExecutorFinish_hook = prevExecutorFinish;
ExecutorEnd_hook = prevExecutorEnd;
}
Those functions are in a file called "myextension.c", compiled into "myextension.dll". I built it in Visual Studio 2015, with following settings:
Configuration Properties -> General, “Configuration Type” = “Dynamic
Library (.dll)”.
C/C++ -> Code Generation, “Enable C++ Exceptions” = “No”,“Advanced”
set “Compile As” = “Compile as C Code (/TC)”.
Linker -> Manifest File, “Generate Manifest” = “No”.
Linker -> Input -> Additional Dependencies, added “postgres.lib” to the
library list.
Configuration Properties -> C/C++ -> General, Additional Include
Directories, added: “include\server\port\win32_msvc”, “include\server\port\win32”, “include\server”, “include”
Solution configuration = Release
Solution Platform = x64 (Installed 64 bit version of PostgreSQL 9.6 on
Windows 10)
In myExecutorXXX functions I check if there are previous ExecutorXXX functions, call them if they exist, if they don't I call the standard_ExecutorXXX function. Here is an example of one of the functions:
static void myExecutorStart(QueryDesc *queryDesc, int eflags) {
if (prevExecutorStart) prevExecutorStart(queryDesc, eflags);
else standard_ExecutorStart(queryDesc, eflags);
FILE *file = NULL;
file = fopen("F:\\query.txt", "a+");
fprintf(file, "Query: %s started!\n", queryDesc->sourceText);
fclose(file);
}
I copied the "myextension.dll" in "../PostgreSQL/9.6/lib" directory, and added a "myextension.control" and "myextension--1.0.sql" to "../PostgreSQL/9.6/share/extension" directory.
myextension.control:
# pg_extension extension
comment = 'myextension!!!'
default_version = '1.0'
myextension--1.0.sql:
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION myextension" to load this file. \quit
In the "postgresql.conf" I added shared_preload_libraries = 'myextension'. After that I connected to a test DB and ran: CREATE EXTENSION myextension;, and restarted the server.
If anyone has any idea what might be causing this, please help.
A couple of comments to get you on the right track:
_PG_fini() will never get called, because modules don't get unloaded.
_PG_init(), however, does get called when the module is loaded. Your main question seems to be why nothing is written to F:\init.txt and other files you use for logging.
On Windows, PostgreSQL normally runs as service. I suspect that the operating system user doesn't have the privileges to write to these files. I know little about Windows and its permission management, but I notice that you do not check the return code of fopen(), so it might well have silently failed.
My recommendation is to use the logging infrastructure instead, e.g. with
elog(LOG, "Init started!");
That will write the message to the PostgreSQL server log and is much more comfortable and less error prone.
Two more comments:
There is no point in creating an extension, because your code does not provide any SQL functions. CREATE EXTENSION myextension is a no-operation.
Don't forget to restart the PostgreSQL server after changing shared_preload_libraries.
I need to say that i am Newbie at C and i only wrote about 100-150 lines of code in C.
I need to read a .properties file with entries like the following:
Value1 = Hello
Value2 = Bye
I would like to get to the Values like this:
bla.getValue("Value1");
So i can work with it like this:
foo = bla.getValue("Value1");
bar = bla.getValue("Value2");
printf("%s - %s",foo,bar);
I don't need them for anything else, than printing them to the screen.
I found two questions here, which went into the right direction, but they couldn't help me in my task:
How to read configuration/properties file in C?
Properties file library for C (or C++)
I tried multiple of the answers of the thread above, but either way my compiler(minGW) doesn't like one of these lines:
using foo::bar;
or
using namespace foo;
When i try to compile my code, i get an error saying:
error: unknown type name 'using'
This is the code where i tried to implement the given solution of the thread above:
#include <windows.h>
#include <stdio.h>
#include <string.h>
using platformstl::properties_file;
int WINAPI WinMain(HINSTANCE a,HINSTANCE b,LPSTR c,int d)
{
char *tPath, *tWindow;
char *search = " ";
tWindow = strtok(c, search);
tPath = strtok(NULL, search);
properties_file properties("%s",tPath);
properties::value_type value1 = properties["Value1"];
properties::value_type value2 = properties["Value2"];
printf("Window: %s; Path: %s; %s %s",tWindow,tPath,value0,value1);
}
I use a WinMain, because the programm is about finding an open Window. I haven't included those parts of the code, because they are irrelevant for my question and worked completely fine. The strtok(); parts are working fine for me too. I need them, because the title of the window to find and the Path of the properties file are both given as commandline arguments:
programm.exe windowtitle path/to/properties/file
As i tried with other answers, which told me to load some libraries, i got to a point, where the needed libraries didn't contain the needed header files. Some of the libraries are even for c++, which i have a restriction on, so i can't use it.
I hope that made things a little clearer, as you may know that i am not used to ask questions here. :)
I solved my Problem with a big Workaround.
This is my final code:
if(vn != NULL){
for(i = 0; i < 1; i++){
if(fgets(temp, BUF, vn) == NULL){
printf("Line is empty");
return 2;
}
}
if(fgets(puffer, BUF, vn) == NULL){
printf("Line is empty");
return 2;
}
tVariable = strtok(puffer, find);
tValue = strtok(NULL, find);
}else {
printf("Unable to read File");
return 2;
}
I just read the second Line of the given file and cut it at the = sign.
I know, that i need to read the second line, because the Property i need is always found in the second line of the .properties file.
I now have my wanted Value in tValue, so i can use it to print it out with printf("%s", tValue).
I want to use a dll-file in my C-Code, but are very confused about the syntax.
My Story: I made a simple function in Matlab ( f(x1,x2)=x1*x2 ), with the "Matlab Coder" I translated it to C-Code and generated an exe, I could run it from the terminal with arguments.Now I generated a dll instead of an exe and want to use the dll.
Since now I could not make Code explanations, I googled, make work for me. I look up Syntax in http://en.cppreference.com/w/ but for my surprise there wasn't even an entry for e.g. GetProcAddress or LoadLirbary.
Here is the C-Code in which I would like to use the dll:
#include <stdio.h>
#include <stdlib.h>
/*
* In my dream I would load the dll function here
* with something like Load(mytimes4.dll)
*/
int main(int argc, char *argv[]) {
double x1,x2,myresult;
//Load Arguments from Terminal
sscanf(argv[1], "%lf", &x1);
sscanf(argv[2], "%lf", &x2);
// Use and print the function from mytimes4.dll
myresult = mytimes4(x1,x2);
printf("%3.2f\n",myresult);
return 0;
}
After generating the dll, Matlab gave me the following folder:
"dll-folder" produced by Matlab
Can someone give me a most simple but complete Code that would work with my example? What files are needed (maybe .def or .exp)? Also for Explanations of the lines involved using the dll I would be gratefull. Or if not, you maybe have some background knowledge that makes the complex syntax reasonable.Thanks in advance!
System information: Windows 7 Pro 64, Matlab 64 2016b, gcc cygwin 64, eclipse ide.
With the link of thurizas I could solve my problem.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686944(v=vs.85).aspx
I copied the code from the side. Below you can see the code with additional comments of mine and with ,in my opinion, more clearly naming. Thus it is probably easier to use for beginners as I am.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
/*Declaration of the function,contained in dll, as pointer with the arbitrary pointer name
"*MYFUNCTIONPOINTER" (not sure if it has to be in big letters).
In my case the function means simply f(x1,x2) = x1*x2 and is thus as double declared*/
typedef double (*MYFUNCTIONPOINTER)(double, double);
int main() {
HINSTANCE hinstLib;
//"myfunction" is the arbitrary name the function will be called later
MYFUNCTIONPOINTER myfunction;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
//Tell the dll file
hinstLib = LoadLibrary(TEXT("mypersonal.dll"));
if (hinstLib != NULL)
{
/* At this line "myfunction" gets its definition from "MYFUNCTIONPOINTER"
and can be used as any other function.The relevant function in the dll has
to be told here.*/
myfunction = (MYFUNCTIONPOINTER) GetProcAddress(hinstLib, "mydllfunction");
// If the function address is valid, call the function.
if (NULL != myfunction)
{
fRunTimeLinkSuccess = TRUE;
// The function can be used.
double myoutput;
myoutput = myfunction(5,7);
printf("%f\n",myoutput);
getchar();
}
// Free the DLL module.
fFreeResult = FreeLibrary(hinstLib);
}
// If unable to call the DLL function, use an alternative.
if (! fRunTimeLinkSuccess)
printf("Message printed from executable\n");
return 0;
}
I have some C code trying to use libharu. Although I can use every function of this library (even UTF8) I can hardly draw images. Here is some very basic code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <setjmp.h>
#include "hpdf.h"
jmp_buf env;
#ifdef HPDF_DLL
void __stdcall
#else
void
#endif
error_handler (HPDF_STATUS error_no,
HPDF_STATUS detail_no,
void *user_data)
{
printf ("ERROR: error_no=%04X, detail_no=%u\n", (HPDF_UINT)error_no,
(HPDF_UINT)detail_no);
longjmp(env, 1);
}
int main (int argc, char **argv)
{
HPDF_Doc pdf;
HPDF_Font font;
HPDF_Page page;
char fname[256];
HPDF_Image image;
strcpy (fname, argv[0]);
strcat (fname, ".pdf");
pdf = HPDF_New (error_handler, NULL);
if (!pdf) {
printf ("error: cannot create PdfDoc object\n");
return 1;
}
/* error-handler */
if (setjmp(env)) {
HPDF_Free (pdf);
return 1;
}
font = HPDF_GetFont (pdf, "Helvetica", NULL);
page = HPDF_AddPage (pdf);
HPDF_Page_SetWidth (page, 550);
HPDF_Page_SetHeight (page, 500);
image = HPDF_LoadPngImageFromFile (pdf, "img.png");
HPDF_SaveToFile (pdf, fname);
HPDF_Free (pdf);
return 0;
}
When I compile this I have ERROR: error_no=1015, detail_no=0. I have found a similar post in stackoverflow: this. However although original poster said the problem is solved it hardly helped mine. I moved img.png to a folder and recompiled the file. Changed the code that says /home/name/path/to/img.png which is the direct path to image. Nothing works. I "always" have the same error, but when I change the name of file I have ERROR: error_no=1017, detail_no=2 which basicly means program cannot find image (according to reference of libharu) So I deduce that program finds img.png; but, it's strange but, cannot allocate the necessary memory. Which is weird because I cannot see any reason for this program not to allocate memory. I have every kind of permission.
I am using GCC 4.7.2 under Ubuntu Quantal Quetzal and libharu 2.3.0 RC2. Thank you for your help.
Hello Equalities of polynomials .
I also encountered the same problem when i integrated the haru sdk in my macOS environment.
The error_handler returned ERROR: error_no=1017, detail_no=2,and then i checked the official document for haru at http://libharu.sourceforge.net/error_handling.html query 0x1017 indicates that the file failed to open, so i suspect that the second parameter of the HPDF_LoadPngImageFromFile method needs to pass an exact png image file path, so after I modified it, the problem was solved, and I hope to help you.
code ad follow:
char filename1[255];
strcpy(filename1, "/Users/xx/Downloads/lusaceg.com.png");
image = HPDF_LoadPngImageFromFile (pdf, filename1);
Faithfully yours.