Attempting to open CD tray - c++

I'm trying to open and close the CD tray of my computer using a piece of code. I have been using MCI commands and have included winmm.lib in the additional dependencies of my project configuration. I've included windows.h and mmsystem.h as well.
The code I'm using is as follows:
mciSendCommand(0, MCI_SET, MCI_SET_DOOR_OPEN, NULL);
mciSendCommand(1, MCI_SET, MCI_SET_DOOR_CLOSED, NULL);
The code builds and runs fine, there's just no CD tray action going on! Can anyone suggest how I need to adapt this?

If you have multiple CD-Drives you should use the following code:
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
int _tmain()
{
DWORD dwBytes;
HANDLE hCdRom = CreateFile(_T("\\\\.\\M:"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hCdRom == INVALID_HANDLE_VALUE)
{
_tprintf(_T("Error: %x"), GetLastError());
return 1;
}
// Open the door:
DeviceIoControl(hCdRom, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &dwBytes, NULL);
Sleep(1000);
// Close the door:
DeviceIoControl(hCdRom, IOCTL_STORAGE_LOAD_MEDIA, NULL, 0, NULL, 0, &dwBytes, NULL);
CloseHandle(hCdRom);
}

You are missing some steps, first you need to open the device.
Try this:
#pragma comment( lib, "winmm.lib" )
#include "stdafx.h"
#include <Windows.h>
#include <mmsystem.h>
int _tmain()
{
MCI_OPEN_PARMS mPar = { 0 };
mPar.lpstrDeviceType = reinterpret_cast<LPCWSTR>(MCI_DEVTYPE_CD_AUDIO);
// Open device
mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID, (DWORD)&mPar);
// Open tray
mciSendCommand(mPar.wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, 0);
// Close tray
mciSendCommand(mPar.wDeviceID, MCI_SET, MCI_SET_DOOR_CLOSED, 0);
// Close device
mciSendCommand(mPar.wDeviceID, MCI_CLOSE, MCI_WAIT, 0);
return 0;
}

Try using DevC++ IDE (WINDOWS ONLY)
Then follow steps:
Step 1:
File > Project > Console Application << Enter
Step 2:
Project Options > Parameters > Linker > write "-lWinmm" in Linker << Enter
Step 3: Open cdtray Copy and paste this small code in your IDE. I recommend DevC++ for this one..
#include<windows.h>
int main(){
mciSendString("set cdaudio door open",0,0,0);
}
Step 4: Close tray, Just change door 'open' to 'closed'
mciSendString("set cdaudio door closed",0,0,0);

Related

Writing to .txt with WriteFile() C++

(Using C++, Windows 10, Microsoft Visual Studio 2017)
Hello, I am new to serial ports but trying to learn how to open, close, read, and write with them
Right now, I am trying to use the CreateFile() and WriteFile() functions to write to a txt file.
I created a .txt file called "write.txt" and saved it in my Documents folder. Then I added it to my project's source files via "Add" --> "Existing Item". The file is empty.
I wrote the program below, hoping I could write to the file, but after running then checking on the file, the file is still empty. The program compiles but I am guessing I have an error somewhere. Am I going about writing to a file correctly?
#include <iostream>
#include <Windows.h>
#include <string>
using namespace std;
int main() {
HANDLE write;
write = CreateFile(TEXT("\\write.txt"), GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (write == INVALID_HANDLE_VALUE) {
DWORD errorWrite = GetLastError();
printf("Error in opening file\n");
printf("Error = 0x%x\n", errorWrite);
}
else {
printf("Opening file successful\n");
}
WriteFile(write, "hello", 5, 0, 0);
CloseHandle(write);
return 0;
}
The output says the file was opened successfully, but the write.txt file remains empty. Any advice?
Thank you in advance :D
You are not accessing the text file that is located in your Documents folder. You are accessing a text file that is located at the root of the drive where the calling process's current working directory is currently pointing at.
You need to explicitly query the OS for the path to the Documents folder (ie, via SHGetFolderPath() or SHGetKnownFolderPath()), and then append your filename to that path.
Also, you are calling WriteFile() incorrectly. In particular, the lpNumberOfBytesWritten parameter is wrong:
lpNumberOfBytesWritten
A pointer to the variable that receives the number of bytes written when using a synchronous hFile parameter. WriteFile sets this value to zero before doing any work or error checking. Use NULL for this parameter if this is an asynchronous operation to avoid potentially erroneous results.
This parameter can be NULL only when the lpOverlapped parameter is not NULL.
And, you are not doing any error handling on WriteFile(), either:
If the function succeeds, the return value is nonzero (TRUE).
If the function fails, or is completing asynchronously, the return value is zero (FALSE). To get extended error information, call the GetLastError function.
Try something more like this instead:
#include <iostream>
#include <string>
#include <Windows.h>
#include <Shlobj.h>
#include <shlwapi.h>
using namespace std;
int main() {
TCHAR path[MAX_PATH] = {};
HRESULT hRes = SHGetFolderPath(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, path);
if (FAILED(hRes)) {
printf("Can't get Documents folder path\nError = 0x%08x\n", hRes);
}
else {
PathAppend(path, TEXT("write.txt"));
HANDLE write = CreateFile(path, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (write == INVALID_HANDLE_VALUE) {
DWORD errorWrite = GetLastError();
printf("Can't open file\nError = %u\n", errorWrite);
}
else {
printf("File opened successful\n");
DWORD written;
if (!WriteFile(write, "hello", 5, &written, NULL)) {
DWORD errorWrite = GetLastError();
printf("Can't write to file\nError = %u\n", errorWrite);
} else {
printf("File written successful\n");
}
CloseHandle(write);
}
}
return 0;
}

Problem trying to start a runnable jar from a C++ application

I need to develop a .exe file that will launch a runnable .jar file which is stored on a subfolder called core. I built the C++ .exe application with sublime text and mingw and it's working fine but there is a small problem that I need to solve. When you execute the .exe file, during a minimum portion of time you can see a black window on screen which is disappearing in some milliseconds and after it the Java .jar application opens. This only happens if I use this .exe. If I double click in the runnable jar the black window doesn't appear.
How can I avoid that black window which dissapears in some milliseconds?
This is the code:
#include <windows.h>
int main()
{
ShellExecute(0, "open", "core.jar", NULL, "core", SW_SHOW);
return 0;
}
I tried also with this code and same result:
ShellExecute(0, "open", "cmd.exe", "/C .\\core\\core.jar", 0, SW_HIDE);
I'm aware there are other similar questions but none of them works for this problem and none of them seems to be applicable to Sublime and gcc.
The problem isn't your call to ShellExecute. Your code is for a console application. Console applications, as one might guess, run in a console (that black window; same as you'd get if you ran cmd.exe).
You can just replace main with WinMain, and simply call ShellExecute in there to launch the jar, and there should be no resulting console window (assuming the jar itself isn't creating one).
See 14 B for how to make a 'windows' app with MingW.
Use CreateProcess() or ShellExecuteEx() which will return you handle to the created process, and with that handle you can kill the process.
Here is an example showing how this works including error handeling.
#include <windows.h>
#include <string>
#include <iostream>
void DisplayError(LPCTSTR errorDesc, DWORD errorCode)
{
TCHAR errorMessage[1024] = TEXT("");
DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
| FORMAT_MESSAGE_MAX_WIDTH_MASK;
FormatMessage(flags,
NULL,
errorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
errorMessage,
sizeof(errorMessage) / sizeof(TCHAR),
NULL);
std::cerr << "Error : " << errorDesc << "\n";
std::cerr << "Code = " << errorCode << "\n";
std::cerr << "Message = " << errorMessage << "\n";
}
int main()
{
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
ZeroMemory(&info, sizeof(info));
info.cb = sizeof(info);
ZeroMemory(&processInfo, sizeof(processInfo));
std::string path = "D:\\Java\\jdk1.6.0_26\\bin\\java.exe";
std::string cmdArgs = "java.exe -jar D:\\temp\\sample.jar";
// Start the child process.
if (CreateProcess(path.c_str(), const_cast<char *>(cmdArgs.c_str()), NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
{
// Wait until child process exits.
WaitForSingleObject(processInfo.hProcess, INFINITE);
// Close process and thread handles.
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
else
{
DWORD errorCode = GetLastError();
DisplayError(TEXT("Unable to execute."), errorCode);
}
//system("pause");
}
Finally I discovered that is enough with adding -mwindows to the gcc compile command:
gcc -o launcher launcher.cpp -mwindows

KQUEUE only works for folder path?

I am use the code (actually copy from hereFSEvents C++ Example)as following, but it can only work for a path, can not work for a file.
I just want to monitor a specific file. How can I do that? thanks
#include <fcntl.h> // for O_RDONLY
#include <stdio.h> // for fprintf()
#include <stdlib.h> // for EXIT_SUCCESS
#include <string.h> // for strerror()
#include <sys/event.h> // for kqueue() etc.
#include <unistd.h> // for close()
int main (int argc, const char *argv[])
{
int kq = kqueue ();
// dir name is in argv[1], NO checks for errors here
int dirfd = open (argv[1], O_RDONLY);
struct kevent direvent;
EV_SET (&direvent, dirfd, EVFILT_VNODE, EV_ADD | EV_CLEAR | EV_ENABLE,
NOTE_WRITE, 0, (void *)argv[1]);
kevent(kq, &direvent, 1, NULL, 0, NULL);
// Register interest in SIGINT with the queue. The user data
// is NULL, which is how we'll differentiate between
// a directory-modification event and a SIGINT-received event.
struct kevent sigevent;
EV_SET (&sigevent, SIGINT, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, NULL);
// kqueue event handling happens after the legacy API, so make
// sure it doesn eat the signal before the kqueue can see it.
signal (SIGINT, SIG_IGN);
// Register the signal event.
kevent(kq, &sigevent, 1, NULL, 0, NULL);
while (1) {
// camp on kevent() until something interesting happens
struct kevent change;
if (kevent(kq, NULL, 0, &change, 1, NULL) == -1) { exit(1); }
// The signal event has NULL in the user data. Check for that first.
if (change.udata == NULL) {
break;
} else {
// udata is non-null, so it's the name of the directory
printf ("%s\n", (char*)change.udata);
}
}
close (kq);
return 0;
}
What operations on the file are being performed that you're missing?
Note that many things that write files don't open the existing file and write to it; they unlink the existing file and replace it with a new one. Because of that, kqueue() won't report that the file that you have open has been written to. You can add NOTE_DELETE to the fflags to try to catch that.

DVD or CD Player?

I want to know if my player is a DVD or CD Player, etc ...
I tried :
SELECT Drive, MediaType, Caption FROM Win32_CDROMDrive
MediaType doesn't work on XP, and not very well on Seven.
I tried on a computer (with Windows 7) with 1 player (Cd Writer/DVD-ROM) in MediaType I found Cd Writer.
Second solution :
I search in "Caption" if I find "DVD"
I tried a software, (SIW - System Information for Windows) and in my Player properties :
Capabilities :
CD Reader : CD ROM, CD R, CD RW
CD Writer : CD R, CD RW
DVD Reader : DVD ROM, DVD R, DVD RW, DVD RAM
DVD Writer : No
SMART Support : No
So, I want to know : with a WMI query (or other solution, I use C++), can I have the same informations or not?
It would be awesome if I could! If I can't, I just keep my "String parsing".
to determine if a drive is DVD or CDROM , you can use the the DeviceIoControl function with the IOCTL_STORAGE_GET_MEDIA_TYPES_EX control code and then check the value of the DeviceType field of the GET_MEDIA_TYPES structure.
Try this sample
#include "stdafx.h"
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#define wszDrive L"\\\\.\\D:"
int wmain(int argc, wchar_t *argv[])
{
BOOL bResult;
HANDLE hDevice = INVALID_HANDLE_VALUE; // handle to the drive to be examined
hDevice = CreateFileW(wszDrive, // drive to open
GENERIC_READ,
FILE_SHARE_READ | // share mode
FILE_SHARE_WRITE,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL); // do not copy file attributes
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
return (FALSE);
}
UCHAR lpOutBuffer[2048];
DWORD nOutBufferSize = sizeof(lpOutBuffer);
ULONG lpBytesReturned;
bResult = DeviceIoControl(hDevice, // device to be queried
IOCTL_STORAGE_GET_MEDIA_TYPES_EX, // operation to perform
NULL, 0, // no input buffer
&lpOutBuffer, nOutBufferSize, &lpBytesReturned,
NULL);
CloseHandle(hDevice);
PGET_MEDIA_TYPES pMediaTypes = (PGET_MEDIA_TYPES) lpOutBuffer;
if (bResult)
{
if (pMediaTypes->DeviceType==FILE_DEVICE_DVD)
{
wprintf(L"DVD\n");
}
else
if (pMediaTypes->DeviceType==FILE_DEVICE_CD_ROM)
{
wprintf(L"CDROM\n");
}
}
else
{
wprintf (L"Failed. Error %ld.\n", GetLastError ());
}
cin.get();
return ((int)bResult);
}

RegOpenKeyEx return ERROR_SUCCESS but it shouldn't (windows 7)

I've got a problem about RegOpenKeyEx, the code:
#include <tchar.h>
#include <stdio.h>
#include <windows.h>
#pragma comment (lib, "Advapi32.lib")
int main () {
TCHAR *keyName = _T("SOFTWARE\\foobar2000\\capabilities");
HKEY key = NULL;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName, 0, KEY_ALL_ACCESS, &key) != ERROR_SUCCESS) {
printf("open key failed!\n");
return -1;
} else {
printf("open key success!\n");
}
TCHAR *value = _T("123");
if (RegSetValueEx(key, _T("xxx"), 0, REG_SZ,
(const BYTE *)value, sizeof(TCHAR) * (_tcslen(value) + 1)) != ERROR_SUCCESS) {
printf("set value failed!\n");
}
RegCloseKey(key);
return 0;
}
Save the code in such as reg.cpp, and in command mode:
cl reg.cpp
and I got reg.exe, run it:
D:\tmp>reg.exe
open key success!
But the value hasn't been written in the registry.
Another strange thing is that if I use the visual studio to create a CLI project, and paste the code into main(), the RegOpenKeyEx() will return false.
The platform is windows 7, and UAC is enabled.
Sounds like you're running into virtualization. IF the app has no manifest, when you try to write to HKLM\Software it actually writes to HKEY_USERS\<User SID>_Classes\VirtualStore\Machine\Software. To prevent this, you can run the app elevated. You might want to add a manifest forcing it to run elevated every time. Alternatively, stop writing to HKLM and use HKCU instead.
As for the C++/CLI part, my guess would be you are given an asInvoker manifest for that one, which suppresses virtualization and results in the attempt to get to HKLM failing.