I am not a native C++ programmer, so I need some help with the following:
I got this code working:
#pragma comment(lib, "winmm.lib")
LPCWSTR openCDCommand = L"set cdaudio door open";
//comes from Windows.h, needs winmm.lib see header includes
int errCode = mciSendString(openCDCommand, 0, 0, 0);
Questions:
Do I need to work with LPCWSTR? Why didn't I find a System::String example?
How should I handle 'string concatination'? I cant simply do L"foo"+L"baar"?
Am I on the totally wrong way to play sounds with mciSendString? (actually I really want to use MCI Command and MCI sendString as i did in other projects before)
Is there another way to include the external function mciSendString so it can handle handles?
The signature of mciSendString is
MCIERROR mciSendString(
LPCTSTR lpszCommand,
LPTSTR lpszReturnString,
UINT cchReturn,
HANDLE hwndCallback);
So, regarding the first 2 parameters, in unicode it will be a wchar pointer and in multibyte it will be a char pointer. It's the signature. You cannot change that and you shouldn't worry about that.
std::wstring someString( L"Foo" );
someString.append( L"bar ");
I would play sound with core audio API, waveOut or maybe DirectSound. But, not with the mciSendString().
I'm afraid I don't understand this one.. can you explain it better?
This now works for me - took some time, but maybe in future this will help others:
#include "vcclr.h" // compile with /clr(!)
int Player::mciSendStringHandle(String ^ givenHandle)
{
pin_ptr<const wchar_t> wch = PtrToStringChars(givenHandle);
return mciSendString(wch, 0, 0, 0);
}
Related
I'm trying to map a file to memory, and calc its hash:
// Declaration in header file which I don't control
void SymCryptSha256(PCBYTE pbData, SIZE_T cbData, PBYTE pbResult);
// MY code
HANDLE hFile = ::CreateFile(...);
HANDLE hMap = ::CreateFileMapping(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr));
byte* pMap = ::MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
BYTE[64] hash;
ULARGE_INTEGER li;
li.LowPart = ::GetFileSize(file , &li.HighPart);
// This compiles in 64-bit, but errors in 32-bit:
// error C4244: 'argument': conversion from 'ULONGLONG' to 'SIZE_T', possible loss of data
::SymCryptSha256(pMap, li.QuadPart, &hash);
This is because SymCryptSha256's second argument is SIZE_T, which in 32-bit compilation is 32-bit. The desired behavior is:
64-bit: Use the entire size, which is li.QuadPart
32-bit: In case size>4GB, MapViewOfFile would fail anyways. So, just use li.LowPart.
Looks to me like I'll need to do this with #ifdefs - is there a more elegant way for it?
In the general case, and using this trick, you could do something like this:
if (li.QuadPart > ((ULONGLONG)((size_t)(-1))) too_big();
size_t result = (size_t)(li.QuadPart);
The compiler should optimize the first line into a no-op in a 64-bit compile.
(In your particular case, you probably don't need it anyway; the code will already have failed.)
Note: as already discussed in the comments, in this particular case it would be preferable, if at all possible, to use a hashing API that allows you to hash the data in chunks.
I'm trying to make a win32 dll that are able to handle ansi and unicode depending what specify in the character set on properties. Unicode or Not Set. ANSI when building in Visual Studio.
The dll has the definition
extern "C" int __stdcall calc(TCHAR *foo)
The definition file is as follow
typedef int (CALLBACK* LPFNDLLCALC)( TCHAR *foo)
Inside the MFC Calling app i load the dll as this
HINSTANCE DllFoo = LoadLibrary(L"foo.dll");
LPFNDLLCALC lpfnDllcalc = (LPFNDLLCALC)GetProcAddress(DllFoo ,"calc");
CString C_SerialNumber;
mvSerialNumber.GetWindowText(C_SerialNumber);
TCHAR* SerialNumber = C_SerialNumber.GetBuffer(0);
LPFNDLLCALC(SerialNumber);
I understand that i make something wrong in the C_SerialNumber.GetBuffer(0) to the TCHAR* pointer. Because in the debugger in the dll only show the first char is passed to the dll. Not the complete string.
How do i get CString to pointer that work in both ansi and unicode.
If change all my code to wchar_t or char in stead of TCHAR i get it to work. Put not with this nativ TCHAR macro.
As I see it you have two options:
Write the code entirely using TCHAR. Then compile the code into two separate DLLs, one narrow and one wide.
Have a single DLL that exports two variants of each function that operates on text. This is how the Windows API is implemented.
If you choose the second option, you don't need to implement each function twice. The primary function is the wide variant. For the narrow variant you convert the input from narrow to wide and then call the wide version. Vice versa for output text. In other words, you use the adapter pattern.
I suppose that you are imagining a third option where you have a single function that can operate on either form of text. Don't go this way. This way abandons type safety and will give you no end of pain. It will also be counter to user's expectations.
As David said, you need to export two separate functions, one for Ansi and one for Unicode, just like the Win32 API does, eg:
#ifdef __cplusplus
extern "C" {
#endif
int WINAPI calcA(LPCSTR foo);
int WINAPI calcW(LPCWSTR foo);
#ifdef __cplusplus
}
#endif
typedef int (WINAPI *LPFNDLLCALC)(LPCTSTR foo);
Then you can do the following:
int WINAPI calcA(LPCSTR foo)
{
return calcW(CStringW(foo));
}
int WINAPI calcW(LPCWSTR foo)
{
//...
}
HINSTANCE DllFoo = LoadLibrary(L"foo.dll");
LPFNDLLCALC lpfnDllcalc = (LPFNDLLCALC) GetProcAddress(DllFoo,
#ifdef UNICODE
"calcW"
#else
"calcA"
#endif
);
CString C_SerialNumber;
mvSerialNumber.GetWindowText(C_SerialNumber);
lpfnDllcalc(C_SerialNumber);
My WPF app consumes a third-party Win32 dll that logs messages via OutputDebugString.
I can see the OutputDebugString messages in Visual Studio or via DebugView, but I don't want to ask my customer to run DebugView. I'd like to capture the messages from OutputDebugString and automatically log them to a file, so if the customer has a problem, I can just ask her to send me that log file.
Is this possible? Or does the user necessarily have to start DebugView, reproduce the error, and then send me the log that way?
Hook OutputDebugStringW. I'd suggest using the Detours library for this.
#include <windows.h>
#include <detours.h>
#pragma comment(lib, "detours.lib")
BOOL SetHook(__in BOOL bState, __inout PVOID* ppPointer, __in PVOID pDetour)
{
if (DetourTransactionBegin() == NO_ERROR)
if (DetourUpdateThread(GetCurrentThread()) == NO_ERROR)
if ((bState ? DetourAttach : DetourDetach)(ppPointer, pDetour) == NO_ERROR)
if (DetourTransactionCommit() == NO_ERROR)
return TRUE;
return FALSE;
{
#define InstallHook(x, y) SetHook(TRUE, x, y)
VOID (WINAPI * _OutputDebugStringW)(__in_z_opt LPCWSTR lpcszString) = OutputDebugStringW;
VOID WINAPI OutputDebugStringHook(__in_z_opt LPCWSTR lpcszString)
{
// do something with the string, like write to file
_OutputDebugStringW(lpcszString);
}
// somewhere in your code
InstallHook((PVOID*)&_OutputDebugStringW, OutputDebugStringHook);
#Cody Gray's suggestion to "write your own debug listener, and then you've basically written an inferior clone of DebugView" sounds like it might actually be an answer to my question.
Here's a C# implementation of a basic OutputDebugString capture tool. I'd seen it in my Googling a couple of times, but my eyes glazed over it, assuming, "that can't possibly be what I want, can it?" Turns out, it just might be the answer to my question.
I'm trying to get some simple piece of code I found on a website to work in VC++ 2010 on windows vista 64:
#include "stdafx.h"
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dResult;
BOOL result;
char oldWallPaper[MAX_PATH];
result = SystemParametersInfo(SPI_GETDESKWALLPAPER, sizeof(oldWallPaper)-1, oldWallPaper, 0);
fprintf(stderr, "Current desktop background is %s\n", oldWallPaper);
return 0;
}
it does compile, but when I run it, I always get this error:
Run-Time Check Failure #2 - Stack around the variable 'oldWallPaper' was corrupted.
I'm not sure what is going wrong, but I noticed, that the value of oldWallPaper looks something like "C\0:\0\0U\0s\0e\0r\0s[...]" -- I'm wondering where all the \0s come from.
A friend of mine compiled it on windows xp 32 (also VC++ 2010) and is able to run it without problems
any clues/hints/opinions?
thanks
The doc isn't very clear. The returned string is a WCHAR, two bytes per character not one, so you need to allocate twice as much space otherwise you get a buffer overrun. Try:
BOOL result;
WCHAR oldWallPaper[(MAX_PATH + 1)];
result = SystemParametersInfo(SPI_GETDESKWALLPAPER,
_tcslen(oldWallPaper), oldWallPaper, 0);
See also:
http://msdn.microsoft.com/en-us/library/ms724947(VS.85).aspx
http://msdn.microsoft.com/en-us/library/ms235631(VS.80).aspx (string conversion)
Every Windows function has 2 versions:
SystemParametersInfoA() // Ascii
SystemParametersInfoW() // Unicode
The version ending in W is the wide character type (ie Unicode) version of the function. All the \0's you are seeing are because every character you're getting back is in Unicode - 16 bytes per character - the second byte happens to be 0. So you need to store the result in a wchar_t array, and use wprintf instead of printf
wchar_t oldWallPaper[MAX_PATH];
result = SystemParametersInfo(SPI_GETDESKWALLPAPER, MAX_PATH-1, oldWallPaper, 0);
wprintf( L"Current desktop background is %s\n", oldWallPaper );
So you can use the A version SystemParametersInfoA() if you are hell-bent on not using Unicode. For the record you should always try to use Unicode, however.
Usually SystemParametersInfo() is a macro that evaluates to the W version, if UNICODE is defined on your system.
I read a very fascinating article that was about programming drivers using the wdk, and one of the functions it used is called ObReferenceObjectByName. This function has given me lots of headaches. The first bad thing is that it's not documented by microsoft. The second thing, is that the language used in the article was C++, and I want to keep my code in plain ol' C. I know that most of the time this shouldn't be a problem, but I haven't - for the life of me - been able to figure out how to include this function.
The code in the article goes something like:
extern "C"{
#include <ntifs.h>
NTSYSAPI NTSTATUS NTAPI ObReferenceObjectByName(PUNICODE_STRING ObjectName,
ULONG Attributes,
PACCESS_STATE AccessState,
ACCESS_MASK DesiredAccess,
POBJECT_TYPE ObjectType,
KPROCESSOR_MODE AccessMode,
PVOID ParseContext OPTIONAL,
PVOID* Object);
}
I've been trying to replicate this for hours. I tried declaring it without the 'extern' keyword, I tried changing the calling convention, I tried changing the includes... I always end up with the error "unresolved external symbol...".
I'm absolutely stumped, so if anyone could offer some advice, I'd be grateful. Thanks.
You wouldn't be reading http://www.codeproject.com/KB/recipes/keystroke-hook.aspx and trying to create your own Keyboard Logger would you?
Anyways, instead of using this, call ZwCreateFile then ObReferenceObjectByHandle instead.
Here is a test C code compiled and built with no problems:
#include <ntddk.h>
NTSYSAPI NTSTATUS NTAPI ObReferenceObjectByName(
PUNICODE_STRING ObjectName,
ULONG Attributes,
PACCESS_STATE AccessState,
ACCESS_MASK DesiredAccess,
POBJECT_TYPE ObjectType,
KPROCESSOR_MODE AccessMode,
PVOID ParseContext OPTIONAL,
PVOID* Object
);
NTSTATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
ObReferenceObjectByName(0, 0, 0, 0, 0, 0, 0, 0);
return STATUS_SUCCESS;
}
I don't know this API, but I can give you a trick that might help you diagnose the problem.
at a command prompt that has MSVC tools in the path
link /dump /exports ???.dll
where ???.dll is the dll were you expect this function to be. This will give you a complete list of exported symbol names and will tell you two things. 1) is the symbol there? and 2) is it being decorated the same as your attempted prototype.
For 32 bit kernel, you should expect this to be called _ObReferenceObjectByName#64,