I want to extract vía SDK a video in format .hik (Hikvision) to MP4. My code is the next:
#include <stdio.h>
#include <stdlib.h>
#include "../SDK/incEn/HCNetSDK.h"
#include "Windows.h"
using namespace std;
int saveRecordFile(int userId, char * srcfile, char * destfile) {
HINSTANCE hGetProcIDDLL = LoadLibrary("D:\\ExtraccionYConversionArchivos\\c++\\Fuente\\SDK\\HCNetSDK.dll");
int bRes = 1;
int hPlayBack = 0;
if ( (hPlayBack = NET_DVR_GetFileByName(userId, srcfile, destfile)) < 0)
{
printf("Error en GetFileByName. Error[$d]\n",NET_DVR_GetLastError());
bRes = -1;
return bRes;
}
if (!NET_DVR_PlayBackControl(hPlayBack, NET_DVR_PLAYSTART,0,NULL))
{
printf("Control de play back fallido [%d]\n", NET_DVR_GetLastError());
bRes = -1;
return bRes;
}
int nPos = 0;
for (nPos = 0; nPos < 100 && nPos >= 0; nPos = NET_DVR_GetDownloadPos(hPlayBack))
{
Sleep(5000);
}
printf("Se obtuvo %d\n", nPos);
if (!NET_DVR_StopGetFile(hPlayBack))
{
printf("Error al detener descarga de archivo [%d]\n",NET_DVR_GetLastError());
bRes = -1;
return bRes;
}
printf("%s\n",srcfile);
if (nPos < 0 || nPos > 100)
{
printf("Error de descarga [%d]\n", NET_DVR_GetLastError());
bRes = -1;
return bRes;
}
else
{
return 0;
}
}
int main()
{
printf("Hello world!\n");
return 0;
}
It uses the HCNetSDK.h header, which throw me an error in multiple lines: syntax error before string constant. This header file have more than 41K lines, and most of the error are after typedef:
typedef void (CALLBACK *MSGCallBack)(LONG lCommand, NET_DVR_ALARMER *pAlarmer, char *pAlarmInfo, DWORD dwBufLen, void* pUser);
NET_DVR_API BOOL __stdcall NET_DVR_SetDVRMessageCallBack_V30(MSGCallBack fMessageCallBack, void* pUser);
What could be the problem? Before this lines, there are more than 6K typedef struct like this:
typedef struct tagNET_DVR_MATRIX_STATUS_V50
{
DWORD dwSize;
BYTE byMainFrameType;
BYTE bySoltNum;
BYTE byBoardNum;
BYTE byLCDPanelStatus;
NET_DVR_MATRIX_SUBBOARD_V50 struMatrixSubboard[MAX_MATRIX_SUBBOARD_NUM];
DWORD dwFanSequence;
DWORD dwFanConnectStatus;
DWORD dwFanOperationStatus;
BYTE byDeviceModel[32];
BYTE byRes[32];
}NET_DVR_MATRIX_STATUS_V50, *LPNET_DVR_MATRIX_STATUS_V50;
And even that I make comments over each typedef struct to catch the mistake, I couldn't figure out how.
A few things to try:
Look for another file that includes this header. Does it compile? What other headers does it use and which of those come before this header in the list?
Can you copy (duplicate and rename) this code into a C file with a simple hello world main function? It might force the compiler to tell you which line the actual problem is on.
Are you using an old compiler? I used to get problems with an old version of Visual Studio - it wasn’t up to date with C99 so it couldn’t compile certain data types (that were no problem for GNU compilers). C standards are sometimes updated and you need to use a suitable compiler (or code in an old style!).
Finally, is it possible to extract or convert the data with ffmpeg? If you can do it on a command line, there’s no need to compile any code.
Related
I am trying to find the file(say marks.txt) in the particular path passed as argument to a function. Is it possible to give the filename and path as arguments to a function which checks if the file exists and prints out the path?
The below function only takes path as argument.
int fileexists(const char *path){
File *ptr = fopen(path, "r");
if (fptr == NULL)
return 0;
fclose(fptr);
return 1;
}
The required function prototype :
int fileexists(const char *path, const char *filename)
There are two parts to this question, and the right answers to them depend on what you're trying to do.
Concatenate a directory name and a file name to form a full path name.
Determine whether a file (referred to by a full path name) exists or not.
Concatenating a directory name and a file name is straightforward. Your friendsstrcpy and strcat will do most of the work. There are a few minor details to be careful of: (a) You'll need a big enough buffer for the full pathname, and you'll need to decide whether to use a fixed-size array (perhaps of size MAX_PATH), or a malloc'ed buffer; (b) you might need to insert an explicit '/' character (and it usually doesn't hurt to stick one in even if the directory string already ends in one); (c) under Windows you might want to use '\\' instead of '/'.
And then determining whether a file named by a full pathname exists is already well answered over at What's the best way to check if a file exists in C?. The big question to ask here is, are you asking whether the file exists in preparation to doing something with the file? If so, you have a serious vulnerability if you check for the file's existence, but then before you do the other thing, something else happens to cause the file to appear or disappear. So rather than checking-and-then-doing, it's usually better to just try doing the other thing, and deal gracefully with any errors.
The function you have checks if the file can be opened, but it will fail for some files that exist but you have no rights to open. I'd use stat instead. To concatenate the path and filename you can use string functions.
The usual Unix C APIs are dismal. It takes lots of effort to do the simplest of things correctly - and even then I'm not sure that I didn't forget some Unix-ism like signal handling or some obscure error cases. I.e. stuff that's rather trivial to get right in modern C++.
I wish someone designed a modern C system API and implemented it for at least Linux, so that our suffering would end...
Usually, string concatenation requires some higher level API to be done while maintaining a modicum of sanity. Thus, the example below uses a strbuilder class to build the string. This makes things vaguely readable and avoids most common mistakes.
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
struct strbuilder {
unsigned items, item;
size_t length, *lengths;
char *str, *dst;
};
bool strbuilder_pass(struct strbuilder *builder, int *rc);
void strcat_str(struct strbuilder *builder, const char *src);
void strcat_c_ifnone(struct strbuilder *builder, char c);
bool strbuilder_is_freed(const struct strbuilder *builder);
int fileExists(const char *path, const char *filename)
{
const char pathSep = '/';
int rc;
struct strbuilder bld = {0};
while (strbuilder_pass(&bld, &rc))
{
strcat_str(&bld, path);
strcat_c_ifnone(&bld, pathSep);
strcat_str(&bld, filename);
if (!rc)
{
struct stat statbuf;
printf("path = %s\n", bld.str);
rc = stat(bld.str, &statbuf);
}
}
assert(strbuilder_is_freed(&bld));
return rc;
}
int main()
{
int rc = fileExists("/", "dev");
assert(rc == 0);
return 0;
}
The string building is controlled by a strbuilder_pass function, which advances the string builder's state through five passes of operation:
Determine the number of items whose width has to be stored (avoids the need to call strlen twice).
Prepare the length storage vector. Determine the length of the buffer needed.
Prepare the output string buffer. Concatenate the elements into the buffer.
Use the output string buffer.
Free the output string buffer.
This API is not particularly special, but fits this use case. Some other ad-hoc approach would work too, but this is IMHO a bit more elegant.
void strbuilder_free(struct strbuilder *builder)
{
free(builder->lengths);
free(builder->str);
memset(builder, 0, sizeof(*builder));
}
bool strbuilder_pass(struct strbuilder *builder, int *rc)
{
if (!builder->length) {// start of pass 1
builder->length = 1; /*term*/
*rc = EAGAIN;
return true;
}
else if (!builder->lengths) // end of pass 1
{
builder->lengths = malloc(sizeof(*builder->lengths) * builder->items);
if (builder->lengths)
return true;
*rc = ENOMEM;
}
else if (!builder->str) // end of pass 2
{
builder->dst = (builder->str = malloc(builder->length));
builder->item = 0;
builder->length = 0;
if (builder->dst) {
*builder->dst = '\0';
return true;
}
*rc = ENOMEM;
}
else if (builder->dst) // end of pass 3
{
while (*builder->dst) { // include optional content
builder->dst++; // skip
builder->length++;
}
builder->dst = NULL;
*rc = 0;
return true;
}
else if (!builder->dst) // end of pass 4 (if any)
{}
else {
*rc = EINVAL;
}
strbuilder_free(builder);
return false;
}
void strcat_str(struct strbuilder *builder, const char *src)
{
if (!src)
return;
if (!builder->lengths) // pass 1
builder->items ++;
else if (!builder->str) // pass 2
{
size_t len = strlen(src);
builder->lengths[builder->item++] = len;
builder->length += len;
}
else if (builder->dst) // pass 3
{
size_t len = builder->lengths[builder->item++];
if (*builder->dst && (!len || *builder->dst != *src))
{
builder->dst++;
builder->length++;
}
memcpy(builder->dst, src, len);
builder->dst += len;
builder->length += len;
*builder->dst = '\0';
}
}
void strcat_c_ifnone(struct strbuilder *builder, char c)
{
if (!builder->lengths) {} // pass 1
else if (!builder->str) // pass 2
{
if (c) builder->length ++;
}
else if (builder->dst) // pass 3
{
if (!builder->length || builder->dst[-1] != c)
*(builder->dst) = c;
}
}
bool strbuilder_is_freed(const struct strbuilder *builder)
{
return !builder || (!builder->lengths && !builder->str);
}
You probably want something like this (no error checking for brevity):
...
#include <string.h> // for str* functions
#include <unistd.h> // for access
#include <stdlib.h> // for malloc
...
int fileexists(const char *path, const char *filename)
{
char *name= malloc(strlen(path) + strlen(filename) + 1);
strcpy(name, path);
strcat(name, filename);
int retval = access(name, F_OK) == 0;
free(name);
return retval;
}
Call like this:
if (fileexists("/some/path/", "somefilename.txt")) ...
On windows you can capturing the stack trace using CaptureStackBackTrace as
void* frames[USHRT_MAX];
USHORT framesCount = CaptureStackBackTrace(0, USHRT_MAX, frames, NULL);
However, capturing it by smaller chunks in a loop to avoid allocating a USHRT_MAX buffer doesn't provide the same result.
This code
#include <Windows.h>
#include <assert.h>
#include <stdio.h>
__declspec(noinline) void CheckStack(void)
{
printf("Checking stack...\n");
void* entireStack[USHRT_MAX];
USHORT frameCount = CaptureStackBackTrace(0, USHRT_MAX, entireStack, NULL);
printf("Stack size is: %u\n", frameCount);
ULONG frameOffset = 1;
for (;;)
{
void* chunk[64];
USHORT framesFound = CaptureStackBackTrace(frameOffset, 64, chunk, NULL);
if (framesFound)
{
if (memcmp(entireStack + frameOffset, chunk, sizeof(chunk)) != 0)
{
printf("Incorrect content\n");
}
frameOffset += (ULONG)framesFound;
}
else
{
break;
}
}
if (frameCount != frameOffset)
{
printf("Incorrect count (%u != %u)\n", frameCount, frameOffset);
}
printf("Done\n");
}
__declspec(noinline) void Test(int i)
{
if (i != 500)
Test(++i);
else
CheckStack();
}
int main()
{
Test(0);
}
produces the following output
Checking stack...
Stack size is: 507
Incorrect count (507 != 257)
Done
when building as cl /Od main.c /link /OUT:main.exe.
Am I using the FramesToSkip parameter incorrectly or why are the counts not equal?
If you are using Windows Server 2003 and Windows XP,
The sum of the FramesToSkip and FramesToCapture parameters must be
less than 63.
That's in document.
Else, as #RbMm says, In the API source code, there is the following logic:
if(FramesToSkip>0xfe)
{
return 0; //There are too many stack structures skipped, returning directly to 0.
}
However, this is not metioned on msdn both in the CaptureStackBackTrace and RtlCaptureStackBackTrace.
I am not going to post the source code here, but prove it in debugging:
1.Create a sample:
#include <Windows.h>
#include <assert.h>
#include <stdio.h>
__declspec(noinline) void CheckStack(void)
{
void* entireStack[USHRT_MAX];
USHORT frameCount = CaptureStackBackTrace(255, USHRT_MAX, entireStack, NULL);
}
__declspec(noinline) void Test(int i)
{
if (i != 500)
Test(++i);
else
CheckStack();
}
int main()
{
Test(0);
}
2. Step into CaptureStackBackTrace in Disassembly:
You can see that dword ptr[ebp+8](the first parameter of CaptureStackBackTrace pushed in stack) will be compared with 0feh(254). If true, return 0.
I am making a program that downloads files to a windows. To do so i used urlmon and the urldownload to file function. Whenever i download a file with the function in question in my windows i only get a prefetch file, but i can't find the file on my hard drive. Please tell me what i am doing wrong?
#include <windows.h>
#include <stdio.h>
typedef HRESULT (WINAPI *UDTF)(LPVOID, LPCTSTR, LPCTSTR, DWORD, LPVOID);
int dl_url(char *url, char *path)
{
int q = 1;
HMODULE hDll;
UDTF URLDownloadToFile;
if((hDll = LoadLibrary("urlmon")))
{
if((URLDownloadToFile = (UDTF)GetProcAddress(hDll, "URLDownloadToFileA")))
{
if(URLDownloadToFile(0, url, path, 0, 0) == 0)
q = 0;
}
FreeLibrary(hDll);
}
return q;
}
Note: I use a 32 bit windows xp to test this program.
I am trying to list all devices attached to my system and after searching found this code which throws up error local function definations are illegal can someone explain what its means please.
Or is my issue because I am trying to use code that was from in C++. Thanks
WORKING CODE
#include <windows.h>
#include <setupapi.h>
#include <stdio.h>
#pragma comment(lib,"SetupAPI")
void print_property
(
__in HDEVINFO hDevInfo,
__in SP_DEVINFO_DATA DeviceInfoData,
__in PCWSTR Label,
__in DWORD Property
)
{
DWORD DataT;
LPTSTR buffer = NULL;
DWORD buffersize = 0;
//
while (!SetupDiGetDeviceRegistryProperty(
hDevInfo,
&DeviceInfoData,
Property,
&DataT,
(PBYTE)buffer,
buffersize,
&buffersize))
{
if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
{
// Change the buffer size.
if (buffer)
{
LocalFree(buffer);
}
// Double the size to avoid problems on
// W2k MBCS systems per KB 888609.
buffer = (LPTSTR)LocalAlloc(LPTR, buffersize * 2);
}
else
{
break;
}
}
wprintf(L"%s %s\n",Label, buffer);
if (buffer)
{
LocalFree(buffer);
}
}
int main()
{
//int setupdi_version()
//{
HDEVINFO hDevInfo;
SP_DEVINFO_DATA DeviceInfoData;
DWORD i;
// Create a HDEVINFO with all present devices.
hDevInfo = SetupDiGetClassDevs(
NULL,
0, // Enumerator
0,
DIGCF_PRESENT | DIGCF_ALLCLASSES);
if (INVALID_HANDLE_VALUE == hDevInfo)
{
// Insert error handling here.
return 1;
}
// Enumerate through all devices in Set.
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData); i++)
{
LPTSTR buffer = NULL;
DWORD buffersize = 0;
print_property(hDevInfo, DeviceInfoData, L"Friendly name :", SPDRP_FRIENDLYNAME);
while (!SetupDiGetDeviceInstanceId(
hDevInfo,
&DeviceInfoData,
buffer,
buffersize,
&buffersize))
{
if (buffer)
{
LocalFree(buffer);
}
if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
{
// Change the buffer size.
// Double the size to avoid problems on
// W2k MBCS systems per KB 888609.
buffer = (LPTSTR)LocalAlloc(LPTR, buffersize * 2);
}
else
{
wprintf(L"error: could not get device instance id (0x%x)\n", GetLastError());
break;
}
}
if (buffer)
{
wprintf(L"\tDeviceInstanceId : %s\n", buffer);
}
print_property(hDevInfo, DeviceInfoData, L"\tClass :", SPDRP_CLASS);
print_property(hDevInfo, DeviceInfoData, L"\tClass GUID :", SPDRP_CLASSGUID);
}
if (NO_ERROR != GetLastError() && ERROR_NO_MORE_ITEMS != GetLastError())
{
// Insert error handling here.
return 1;
}
// Cleanup
SetupDiDestroyDeviceInfoList(hDevInfo);
system ("pause");
return 0;
}
You have another function defined inside the body of main; this is invalid C. Move it outside of main.
The code will compile and run if you comment out the following two lines as shown:
// int setupdi_version()
// {
I think the original code is from a function named setupdi_version() and it got mangled a bit when you tried to change it to main(). Note: it looks like the original source code is from here.
To answer your follow-on problem. Those are linker errors. You need to tell Visual Studio which .lib file(s) to link against. You can do that in the Visual Studio project dependencies or just add the following to the top of the source code.
#pragma comment(lib,"SetupAPI")
everyone... I've just started to learn how to create process and thread using Windows API. My code does work if I want thread to display integer on the screen but it doesn't work when using array of chars... Can someone tell me what am I doing wrong? The code:
#include<stdio.h>
#include<Windows.h>
#include<conio.h>
#include<tchar.h>
#include<strsafe.h>
#include<string.h>
#define N 4
#define bufferSize 255
DWORD WINAPI Threader(LPVOID Parameter);
typedef struct Data {
char value[bufferSize];
} Data, *pToData;
int main()
{
int i;
char c[bufferSize];
pToData threadData[N];
HANDLE handleArray[N];
DWORD threadID[N];
FILE *file=fopen("niti.txt", "r");
for(i=0; i<N; i++)
{
fscanf(file, "%s", c);
threadData[i] = (pToData) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Data));
strcpy(threadData[i]->value, c);
handleArray[i]=CreateThread(NULL, 0, Threader, threadData[i], 0, &threadID[i]);
}
WaitForMultipleObjects(N, handleArray, TRUE, INFINITE);
for(i=0; i<N; i++)
{
CloseHandle(handleArray[i]);
if(threadData[i] != NULL)
{
HeapFree(GetProcessHeap(), 0, threadData[i]);
threadData[i] = NULL;
}
}
fclose(file);
return 0;
}
DWORD WINAPI Threader(LPVOID Parameter)
{
HANDLE hStdOut;
TCHAR messageBuffer[bufferSize];
size_t cchStringSize;
DWORD dwChars;
pToData dataArray;
char temp[bufferSize];
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if( hStdOut == INVALID_HANDLE_VALUE )
return 1;
dataArray=(pToData)Parameter;
StringCchPrintf(messageBuffer, bufferSize, TEXT("Parameter = %s\n"), dataArray->value);
StringCchLength(messageBuffer, bufferSize, &cchStringSize);
WriteConsole(hStdOut, messageBuffer, (DWORD)cchStringSize, &dwChars, NULL);
return 0;
}
If I change value in my struct to int and do the same in main the output is correct. Any suggestions?
Thank you!
You are probably compiling for Unicode but outputting a char array. Your symptoms sound like an encoding mismatch and Unicode output function mis-matched against ANSI char array is the mismatch that results in lots of questions marks.
In other words I hypothesise that your code resolves StringCchPrintf as StringCchPrintfW. And you then fail to satisfy the contract by passing char* rather than wchar_t* when you pass dataArray->value.
Use wchar_t or TCHAR instead of char for dataArray->value. Or call the A version of the output functions. Or compile for ANSI.