I'm creating an IStream as follow:
IStream* stream;
result = CreateStreamOnHGlobal(0, TRUE, &stream);
Then I have a CImage object that I save to this stream:
image->Save(stream, Gdiplus::ImageFormatBMP);
I need to get the size of bytes written to this IStream.
How can I do this?
There is no Length or something like this in the IStream...
thanks!
IStream::Stat should do what you want.
Or you can use:
ULARGE_INTEGER liSize;
IStream_Size(pStream, &liSize);
other functions you might find useful in this context:
IStream_Reset(pStream); // reset seek position to beginning
IStream_Read(pStream, mem, size);
Both IStream_Size as well as IStream::Stat can be used to request the size. IStream_Size appears to be a convenience wrapper around IStream::Stat (that's oddly only available as a C COM macro). If that is indeed the case then there's a lot of data queried: An entire STATSTG, optionally without the pwcsName member.
In that case, a less costly way to get the same information would be IStream::Seek:
HRESULT get_size(IStream* stream, ULARGE_INTEGER& size) {
return IStream->Seek({}, STREAM_SEEK_END, &size);
}
This changes the stream's current read or write pointer. If you need to save the current position you can use the following:
ULARGE_INTEGER current{};
stream->Seek({}, STREAM_SEEK_CUR, ¤t);
Related
I am struggling at connecting two APIs. From one I get a Windows::Storage::IBuffer, and the other demands a ComPtr<IStream>. I do not seem to find a way to bridge these two, even if I wanted to do a copy of the data in the stream.
So far the only way forward from IBuffer is to create a Windows::Storage::Streams::DataReader::FromBuffer(buffer). From there, I can ReadBytes to get Platform::Array<unsigned char> array, but then what?
Thanks!
There may be other methods to get a COM compatible IStream interface for the IBuffer but if you have the data bytes you can create a COM IStream on memory using the CreateStreamOnHGlobal API then copying the bytes into the new IStream. Don't forget to reset the seek pointer before handing it out.
[DllImport("ole32.dll")]
private static extern int CreateStreamOnHGlobal(IntPtr hGlobal, bool fDeleteOnRelease, out IStream ppstm);
System.Runtime.InteropServices.ComTypes stm;
if (CreateStreamOnHGlobal(IntPtr.Zero, true, out stm) == 0)
{
stm.Write( ...data for the stream... );
stm.Seek(0, 0, IntPtr.Zero); // seek to start of stream
}
Is there a single standard C/C++ function which takes either a file handle/pointer or a pointer to an in-memory buffer and reads data from the file/buffer?
I have a function which pulls data from a file, performs operations on said data, and sends it out over a socket. I also have a function that takes data in the form of a char buffer, performs exactly the same operations on that data, and sends it over a socket. This problem isn't that hard. I just thought it would be convenient if there was a function like
read(void *dest, void *src, int src_type, size_t amount)
In C++ you can use std::istream as an abstraction on top of a file with an std::ifstream implementation, or an in-memory buffer with an std::istringstream implementation.
The beauty of this approach is that your function does not need to know about the implementation type, because receiving the argument by reference would be sufficient:
void readData(std::istream& in_data) {
...
}
The caller would then construct an appropriate implementation, and pass it to readData.
Sounds like you want to use the operator>>() on an input stream (std::istream), which can either be a filestream, a iostream or a stringstream
I don't know about windows but it will work in Linux.
void readif(int fd ,char *src,size_t nbytes){
read(fd,src,nbytes);
//error handler code
//Other stuffs
}
int fd = open(file);
//for std::input fd = 0
//for in memory data use mmap
mmap
open
read
I am trying to make an audio player that plays .wav files. I wrote a function ReadWaveFile(CString szFilename) for reading the wave data of the file into the WAVEHDR structure. In this function
BOOL CWavePlay::ReadWaveFile(CString szFilename)
{
hmmio = mmioOpen((LPTSTR)&szFilename,NULL,MMIO_READ);
ASSERT(hmmio); //error here: hmmio=0x00000000
if(hmmio==0)
return FALSE;
....
}
mmioOpen is always returning 0 whenever I pass a filepath to this function for opening the specified file. And what baffles me is when i pass the filepath explicitly in mmioOpen API the code works; i.e., a valid handle is returned.
can some body explain why is this happening??
What will happen when you say
MessageBox(NULL,(LPTSTR)&szFilename,"Foo",MB_ICONINFORMATION);
When passing strings to system functions you will need to pick up the pointer to the raw string. For example, if you want to use an std::string object to build your path you will need to say
mmioOpen(filename.c_str(),NULL,MMIO_READ);
Your cast assumes from CString* to LPTSTR assumes that a CString is binary compatible with a LPTSRT which is not the case. When you write LPCTSTR on szFilename you will invoke a cast operator defined on CStrings that converts it to apropriate format. Did you tried just
hmmio = mmioOpen((LPCTSTR)szFilename,NULL,MMIO_READ);
The last cast does not do anything real here so it should be enough.
I've been playing around with the windows clipboard. I noticed that you can only view the clipboard if you supply a format. I've seen programs that can dump the raw contents of the clipboard. Look at http://www.autohotkey.com/docs/misc/Clipboard.htm#ClipboardAll for an example of what I mean.
Is there a way to do something similar, what I want to do is be able to back up the clipboard, manipulate it, then restore it when my program is done.
I'm looking for a non-.net solution if that's actually a thing
EDIT:
I tried this so far:
struct clipData {
vector<void*> data;
vector<int> size;
};
struct clipData saveClipboard(int &size) {
clipData ret;
UINT currentFormat = 0;
HGLOBAL hData;
if (OpenClipboard(0)) {
while(currentFormat = EnumClipboardFormats(currentFormat)) {
hData = GetClipboardData(currentFormat);
int currentClipboardFormatSize = GlobalSize(hData); //Only works with text formats. Help!
char *savedClipboardData = new char[currentClipboardFormatSize];
char *ptrToData = (char*) GlobalLock(hData);
memcpy(savedClipboardData, ptrToData, currentClipboardFormatSize);
ret.data.push_back(savedClipboardData);
ret.size.push_back(currentClipboardFormatSize);
}
CloseClipboard();
}
return ret;
}
But the problem is theres no way to tell how big the clipboard is in each format
There's no "raw" data involved. Just enumerate all the formats currently on the clipboard, and fetch and save the contents of each format. But be careful of automatic format conversions.
If you carefully read the autohotkey documentation you linked, it even tells you that it's retrieving each format separately, and that it may only succeed in retrieving a subset of the formats.
MSDN has all the examples you need to know to manipulate clipboard data using Clipboard API.
im using WIN32_FIND_DATA to store the data findfirstfile outputs. i want the file location (C:\file) as a string but i don't know how to get it or any other data from it.
Edit: here is my code
PTSTR pszFileName;
PTSTR pszFileName2[100];
if (search_handle)
{
do
{
pszFileName = file.cFileName;
pszFileName2[loop] = pszFileName;
Sleep(100);
loop++;
std::wcout << file.cFileName << std::endl;
}
while(FindNextFile(search_handle,&file));
CloseHandle(search_handle);
}
WIN32_FIND_DATA is a struct. Check out the cFileName member.
For example:
WIN32_FIND_DATA FindData = {0};
HANDLE hFind = FindFirstFile(pszPattern, &FindData);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
PTSTR pszFileName = FindData.cFileName;
// TODO: Use pszFileName in some way...
} while (FindNextFile(hFind, &FindData));
FindClose(hFind);
}
Update in response to comments
In this example the storage for the string is on the stack, and the same buffer is used for every call. This means that every FindNextFile() overwrites the previous string. You will have to make a copy of the string.
Since you're using C++ and classes in std I suggest you store it in std::string (or better yet, make sure you define UNICODE and _UNICODE and use wstring.) Initializing a new string class will do the allocation and copying on your behalf.
Alternatively you can copy the string using the typical C techniques (for example: using malloc + memcpy, strdup, or similar), but it sounds like you might want a refresher in strings, pointers, and memory allocation in C before you get to that.
By the way -- to check for error, your code compares the find handle against NULL; this is incorrect. FindFirstFile() returns INVALID_HANDLE_VALUE (which works out to (HANDLE)-1) on failure. Additionally, to close the handle you will want to use FindClose(), and not CloseHandle(). (A "find handle" isn't really a handle to a kernel object in the same sense that a file handle, handle to a module, or a thread or process handle is. They've just overloaded the type.)
The problem is that you're storing the address of the filename in your array. Each time that FindNextFile() is called, it replaces the data in the struct with the information for the next file. You need to allocate memory for the string in your array, and then copy the string from the structure to your array (using something like strncpy_s(), probably).
Your code is just storing the pointer to the filename member of the struct, once per found file. If you look at the address each element in the array is pointing to, they're all pointing to the same place.