Convention wisdom to eject a USB drive on Windows is the following sequence:
CreateFile (drive letter, with read/write rights, file share read and write)
DeviceIoControl(FSCTL_LOCK_VOLUME)
DeviceIoControl(FSCTL_DISMOUNT_VOLUME)
DeviceIoControl(IOCTL_STORAGE_MEDIA_REMOVAL) PreventMediaRemoval = FALSE
DeviceIoControl(IOCTL_STORAGE_EJECT_MEDIA)
This worked fine until a recent change in Windows 10 (not sure when). Now the drive is still properly ejected, but then Windows immediately remounts the drive.
What needs to be done to eject the drive until the user removes it and puts it in again?
Using CM_Request_Device_EjectW API works for me. You can have a try.
The following is the complete code I tested and it from "How to Prepare a USB Drive for Safe Removal" at codeproject.
(Here the "F" is my USB drive letter. Replace it using your own one.)
#include <stdio.h>
#include <windows.h>
#include <Setupapi.h>
#include <winioctl.h>
#include <winioctl.h>
#include <cfgmgr32.h>
//-------------------------------------------------
DEVINST GetDrivesDevInstByDeviceNumber(long DeviceNumber, UINT DriveType, char* szDosDeviceName);
//-------------------------------------------------
//-------------------------------------------------
int main()
{
char DriveLetter = 'F';
DriveLetter &= ~0x20; // uppercase
if (DriveLetter < 'A' || DriveLetter > 'Z') {
return 1;
}
char szRootPath[] = "F:\\"; // "X:\" -> for GetDriveType
szRootPath[0] = DriveLetter;
char szDevicePath[] = "F:"; // "X:" -> for QueryDosDevice
szDevicePath[0] = DriveLetter;
char szVolumeAccessPath[] = "\\\\.\\F:"; // "\\.\X:" -> to open the volume
szVolumeAccessPath[4] = DriveLetter;
long DeviceNumber = -1;
// open the storage volume
HANDLE hVolume = CreateFile(szVolumeAccessPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
if (hVolume == INVALID_HANDLE_VALUE) {
return 1;
}
// get the volume's device number
STORAGE_DEVICE_NUMBER sdn;
DWORD dwBytesReturned = 0;
long res = DeviceIoControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL);
if (res) {
DeviceNumber = sdn.DeviceNumber;
}
CloseHandle(hVolume);
if (DeviceNumber == -1) {
return 1;
}
// get the drive type which is required to match the device numbers correctely
UINT DriveType = GetDriveType(szRootPath);
// get the dos device name (like \device\floppy0) to decide if it's a floppy or not - who knows a better way?
char szDosDeviceName[MAX_PATH];
res = QueryDosDevice(szDevicePath, szDosDeviceName, MAX_PATH);
if (!res) {
return 1;
}
// get the device instance handle of the storage volume by means of a SetupDi enum and matching the device number
DEVINST DevInst = GetDrivesDevInstByDeviceNumber(DeviceNumber, DriveType, szDosDeviceName);
if (DevInst == 0) {
return 1;
}
PNP_VETO_TYPE VetoType = PNP_VetoTypeUnknown;
WCHAR VetoNameW[MAX_PATH];
VetoNameW[0] = 0;
bool bSuccess = false;
// get drives's parent, e.g. the USB bridge, the SATA port, an IDE channel with two drives!
DEVINST DevInstParent = 0;
res = CM_Get_Parent(&DevInstParent, DevInst, 0);
for (long tries = 1; tries <= 3; tries++) { // sometimes we need some tries...
VetoNameW[0] = 0;
// CM_Query_And_Remove_SubTree doesn't work for restricted users
//res = CM_Query_And_Remove_SubTreeW(DevInstParent, &VetoType, VetoNameW, MAX_PATH, CM_REMOVE_NO_RESTART); // CM_Query_And_Remove_SubTreeA is not implemented under W2K!
//res = CM_Query_And_Remove_SubTreeW(DevInstParent, NULL, NULL, 0, CM_REMOVE_NO_RESTART); // with messagebox (W2K, Vista) or balloon (XP)
res = CM_Request_Device_EjectW(DevInstParent, &VetoType, VetoNameW, MAX_PATH, 0);
//res = CM_Request_Device_EjectW(DevInstParent, NULL, NULL, 0, 0); // with messagebox (W2K, Vista) or balloon (XP)
bSuccess = (res == CR_SUCCESS && VetoType == PNP_VetoTypeUnknown);
if (bSuccess) {
break;
}
Sleep(500); // required to give the next tries a chance!
}
if (bSuccess) {
printf("Success\n\n");
return 0;
}
printf("failed\n");
printf("Result=0x%2X\n", res);
if (VetoNameW[0]) {
printf("VetoName=%ws)\n\n", VetoNameW);
}
return 1;
}
//-----------------------------------------------------------
//----------------------------------------------------------------------
// returns the device instance handle of a storage volume or 0 on error
//----------------------------------------------------------------------
DEVINST GetDrivesDevInstByDeviceNumber(long DeviceNumber, UINT DriveType, char* szDosDeviceName)
{
bool IsFloppy = (strstr(szDosDeviceName, "\\Floppy") != NULL); // who knows a better way?
GUID* guid;
switch (DriveType) {
case DRIVE_REMOVABLE:
if (IsFloppy) {
guid = (GUID*)&GUID_DEVINTERFACE_FLOPPY;
}
else {
guid = (GUID*)&GUID_DEVINTERFACE_DISK;
}
break;
case DRIVE_FIXED:
guid = (GUID*)&GUID_DEVINTERFACE_DISK;
break;
case DRIVE_CDROM:
guid = (GUID*)&GUID_DEVINTERFACE_CDROM;
break;
default:
return 0;
}
// Get device interface info set handle for all devices attached to system
HDEVINFO hDevInfo = SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDevInfo == INVALID_HANDLE_VALUE) {
return 0;
}
// Retrieve a context structure for a device interface of a device information set
DWORD dwIndex = 0;
long res;
BYTE Buf[1024];
PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)Buf;
SP_DEVICE_INTERFACE_DATA spdid;
SP_DEVINFO_DATA spdd;
DWORD dwSize;
spdid.cbSize = sizeof(spdid);
while (true) {
res = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, guid, dwIndex, &spdid);
if (!res) {
break;
}
dwSize = 0;
SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, NULL, 0, &dwSize, NULL); // check the buffer size
if (dwSize != 0 && dwSize <= sizeof(Buf)) {
pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes!
ZeroMemory(&spdd, sizeof(spdd));
spdd.cbSize = sizeof(spdd);
long res = SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, pspdidd, dwSize, &dwSize, &spdd);
if (res) {
// in case you are interested in the USB serial number:
// the device id string contains the serial number if the device has one,
// otherwise a generated id that contains the '&' char...
/*
DEVINST DevInstParent = 0;
CM_Get_Parent(&DevInstParent, spdd.DevInst, 0);
char szDeviceIdString[MAX_PATH];
CM_Get_Device_ID(DevInstParent, szDeviceIdString, MAX_PATH, 0);
printf("DeviceId=%s\n", szDeviceIdString);
*/
// open the disk or cdrom or floppy
HANDLE hDrive = CreateFile(pspdidd->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hDrive != INVALID_HANDLE_VALUE) {
// get its device number
STORAGE_DEVICE_NUMBER sdn;
DWORD dwBytesReturned = 0;
res = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL);
if (res) {
if (DeviceNumber == (long)sdn.DeviceNumber) { // match the given device number with the one of the current device
CloseHandle(hDrive);
SetupDiDestroyDeviceInfoList(hDevInfo);
return spdd.DevInst;
}
}
CloseHandle(hDrive);
}
}
}
dwIndex++;
}
SetupDiDestroyDeviceInfoList(hDevInfo);
return 0;
}
Hi I am currently working on a project where we are creating a UDP server to communicate with a KUKA robot. We are able to establish the connection with the robot and exchange the data back and forth but when an event occurs such as the robot faulting out due to motor over torque. So to detect this fault we have added a timeout to the code so that the main dialog box will close and reopen so that all the variables will be reinitialized and we can set the connection to reestablish.
Heres the server code:
#include "stdafx.h"
#include "HapticRobot.h"
#include "CMaths.h"
using namespace chai3d;
#include <winsock.h>
using namespace std;
#pragma comment(lib, "Ws2.lib")
#include <fstream>
#include <string>
#include <sstream>
DWORD WINAPI DoGravity(LPVOID lpParameter);
#define REFRESH_INTERVAL 0 // sec
const int kBufferSize = 1024;
int nTempHold;
extern HapticDevice hd;
extern HWND g_hWndHapticBox;
extern bool bRobotInMotion, bRobotConnectInit, bRobotConnected;
extern Handles hc;
bool err;
std::string stSend, stSendXML, stLine;
std::string stRobotStatus , stAppend;
TCHAR *chRobotStatus;
//variables for timeout
fd_set fds;
int n;
struct timeval tv;
//// Prototypes ////////////////////////////////////////////////////////
SOCKET SetUpListener(const char* pcAddress, int nPort);
bool EchoIncomingPackets(SOCKET sd);
//// DoWinsock /////////////////////////////////////////////////////////
// The module's driver function -- we just call other functions and
// interpret their results.
int DoWinsock(const char* pcAddress, int nPort)
{
int nRetval = 0;
ifstream inFile("HardDisk/ExternalData.xml");
if (inFile.is_open())
{
while ( inFile.good() )
{
getline ( inFile, stLine);
stSendXML.append(stLine);
}
inFile.close();
}
SendDlgItemMessage(g_hWndHapticBox, IDC_LIST_Server, LB_INSERTSTRING, 0, (LPARAM)L"Establishing the listener...");
SOCKET ListeningSocket = SetUpListener(pcAddress, htons(nPort));
SendDlgItemMessage(g_hWndHapticBox, IDC_LIST_Server, LB_INSERTSTRING, 0, (LPARAM)L"Waiting for connections...");
bRobotConnectInit = true;
SetDlgItemText(g_hWndHapticBox, IDC_STATIC_RobotStatus, _T("Waiting for robot"));
while (1)
{
EchoIncomingPackets(ListeningSocket);
bRobotConnected = false;
bRobotConnectInit = true;
SendDlgItemMessage(g_hWndHapticBox, IDC_LIST_Server, LB_INSERTSTRING, 0, (LPARAM)L"Acceptor restarting...");
}
}
//// SetUpListener /////////////////////////////////////////////////////
// Sets up a listener on the given interface and port, returning the
// listening socket if successful; if not, returns INVALID_SOCKET.
SOCKET SetUpListener(const char* pcAddress, int nPort)
{
u_long nInterfaceAddr = inet_addr(pcAddress);
if (nInterfaceAddr != INADDR_NONE)
{
SOCKET sd = socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in sinInterface;
sinInterface.sin_family = AF_INET;
sinInterface.sin_addr.s_addr = nInterfaceAddr;
sinInterface.sin_port = nPort;
if (bind(sd, (sockaddr*)&sinInterface,
sizeof(sockaddr_in)) != SOCKET_ERROR)
{
return sd;
}
}
return INVALID_SOCKET;
}
//// EchoIncomingPackets ///////////////////////////////////////////////
// Bounces any incoming packets back to the client. We return false
// on errors, or true if the client closed the socket normally.
bool EchoIncomingPackets(SOCKET sd)
{
// Read data from client
std::string stReceive;
std::string stIPOC;
std::wstring stTime;
int nStartPos, nEndPos;
char acReadBuffer[kBufferSize], acWriteBuffer[512];
int nReadBytes;
struct sockaddr_in clientAddr;
int sockAddrSize = sizeof(struct sockaddr_in);
//declarations for the low pass filter
int CURRENT_VALUE = 2;
double T = .004, w_co, OMEGA_co, f_co;
hd.bFirstRunRobot = true;
do
{
//This will be to timeout the socket connection
FD_ZERO(&fds);
FD_SET(sd, &fds);
tv.tv_sec = 5;
tv.tv_usec = 0;
n = select (sd, &fds, NULL, NULL, &tv );
if (n == 0)
{
PostMessage(g_hWndHapticBox,WM_CLOSE, 0, 0);
Sleep(5000);
PostMessage(g_hWndHapticBox, WM_INITDIALOG, 0, 0);
Sleep(1000);
//printf("Timeout..\n");
//HapticBox(HWND, UINT, WPARAM, LPARAM);
//return 0;
}
else if (n == -1)
{
printf("Error..\n");
return 1;
}
// end timeout
nReadBytes = recvfrom(sd, acReadBuffer, sizeof(acReadBuffer), 0, (struct sockaddr*)&clientAddr, &sockAddrSize);
//nReadBytes = recvfrom(sd, acReadBuffer, sizeof(acReadBuffer), MSG_PEEK, (struct sockaddr*)&clientAddr, &sockAddrSize);
//if (nReadBytes == SOCKET_ERROR)
//{
// SetDlgItemText(g_hWndHapticBox, IDC_STATIC_RobotStatus, _T("ERROR"));
//}
if (nReadBytes < 0 || nReadBytes == 0)
{
SetDlgItemText(g_hWndHapticBox, IDC_STATIC_RobotStatus, _T("ERROR 1"));
return true;
}
if (nReadBytes > 0)
{
if (bRobotConnectInit)
{
bRobotConnectInit = false;
bRobotConnected = true;
SetDlgItemText(g_hWndHapticBox, IDC_STATIC_RobotStatus, _T("Connected to Robot"));
}
}
stSend = stSendXML;
stReceive = acReadBuffer;
nStartPos = stReceive.find ("<IPOC>") + 6;
nEndPos = stReceive.find ("</IPOC>");
stIPOC = stReceive.substr (nStartPos, nEndPos - nStartPos);
nStartPos = stSend.find ("<IPOC>") + 6;
nEndPos = stSend.find ("</IPOC>");
stSend.replace(nStartPos, nEndPos - nStartPos, stIPOC);
//Raw sensor data
nStartPos = stReceive.find ("RFx=") + 5;
nEndPos = stReceive.find ("RFy=") - 2;
hd.stRFx = stReceive.substr (nStartPos, nEndPos - nStartPos);
hd.szRFx = hd.stRFx.c_str();
hd.RFx = strtod(hd.szRFx, NULL);
hd.RFx = hd.RFx * 0.22;
nStartPos = stReceive.find ("RFy=") + 5;
nEndPos = stReceive.find ("RFz=") - 2;
hd.stRFy = stReceive.substr (nStartPos, nEndPos - nStartPos);
hd.szRFy = hd.stRFy.c_str();
hd.RFy = strtod(hd.szRFy, NULL);
hd.RFy = hd.RFy * 0.22;
**//...more XML stuff...//**
//data the is to be sent to the robot
if (hd.FirstTimePosition)
{
hd.RobotXStartPosition = hd.RobotXPosition;
hd.RobotYStartPosition = hd.RobotYPosition;
hd.RobotZStartPosition = hd.RobotZPosition;
hd.FirstTimePosition = false;
}
if(hd.LinearScale == 4)
{
f_co = 0.5;
}
else if (hd.LinearScale == 3)
{
f_co = 0.5;
}
else if (hd.LinearScale == 2)
{
f_co = 1;
}
else if (hd.LinearScale == 1)
{
f_co = 2;
}
else if (hd.LinearScale == 0.5)
{
f_co = 2;
}
else
{
f_co = 0.5;
}
if (hd.Fz < hd.MaxForcePos)
{
hd.ForceLimitPosZ = false;
}
if (hd.Fz > hd.MaxForceNeg)
{
hd.ForceLimitNegZ = false;
}
if (hd.Fz > hd.MaxForcePos || hd.ForceLimitPosZ)
{
if (!hd.ForceLimitPosZ)
{
hd.CurrentZtoRobotPosition = hd.ZtoRobot;
}
if (hd.CurrentZtoRobotPosition >= hd.ZtoRobot)
{
hd.NewZtoRobot = hd.PreviousZtoRobot;
hd.ForceLimitPosZ = true;
}
else
{
hd.ForceLimitPosZ = false;
}
}
if (hd.ForceLimitPosZ)
{
hd.ForceZtoRobot = hd.NewZtoRobot;
}
else
{
hd.ForceZtoRobot = hd.ZtoRobot;
}
w_co = f_co * C_TWO_PI;
OMEGA_co = (2/T) * cTanRad((w_co * T) / 2);
hd.raw_x[CURRENT_VALUE] = hd.XtoRobot;
hd.raw_y[CURRENT_VALUE] = hd.YtoRobot;
hd.raw_z[CURRENT_VALUE] = hd.ForceZtoRobot;
hd.filtered_x[CURRENT_VALUE] = (pow(((OMEGA_co) / ((2 / T) + OMEGA_co)), 2)) *
((hd.raw_x[CURRENT_VALUE]) + (2 * hd.raw_x[CURRENT_VALUE - 1] + hd.raw_x[CURRENT_VALUE - 2]))
- (((2 * (OMEGA_co - (2 / T))) / ((2 / T) + OMEGA_co)) * hd.filtered_x[CURRENT_VALUE - 1])
- ((pow(((OMEGA_co - (2 / T)) / ((2 / T) + OMEGA_co)),2)) * hd.filtered_x[CURRENT_VALUE - 2]);
**//more digital filter stuff//**
hd.raw_x[CURRENT_VALUE - 2] = hd.raw_x[CURRENT_VALUE - 1];
hd.raw_y[CURRENT_VALUE - 2] = hd.raw_y[CURRENT_VALUE - 1];
hd.raw_z[CURRENT_VALUE - 2] = hd.raw_z[CURRENT_VALUE - 1];
hd.raw_x[CURRENT_VALUE - 1] = hd.raw_x[CURRENT_VALUE];
hd.raw_y[CURRENT_VALUE - 1] = hd.raw_y[CURRENT_VALUE];
hd.raw_z[CURRENT_VALUE - 1] = hd.raw_z[CURRENT_VALUE];
hd.filtered_x[CURRENT_VALUE - 2] = hd.filtered_x[CURRENT_VALUE - 1];
hd.filtered_y[CURRENT_VALUE - 2] = hd.filtered_y[CURRENT_VALUE - 1];
hd.filtered_z[CURRENT_VALUE - 2] = hd.filtered_z[CURRENT_VALUE - 1];
hd.filtered_x[CURRENT_VALUE - 1] = hd.filtered_x[CURRENT_VALUE];
hd.filtered_y[CURRENT_VALUE - 1] = hd.filtered_y[CURRENT_VALUE];
hd.filtered_z[CURRENT_VALUE - 1] = hd.filtered_z[CURRENT_VALUE];
hd.stXtoRobot = dtostr(hd.filtered_x[CURRENT_VALUE]);
nStartPos = stSend.find ("X=") + 3;
stSend.replace(nStartPos, 6, hd.stXtoRobot);
hd.stYtoRobot = dtostr(hd.filtered_y[CURRENT_VALUE]);
nStartPos = stSend.find ("Y=") + 3;
stSend.replace(nStartPos, 6, hd.stYtoRobot);
hd.stZtoRobot = dtostr(hd.filtered_z[CURRENT_VALUE]);
nStartPos = stSend.find ("Z=") + 3;
stSend.replace(nStartPos, 6, hd.stZtoRobot);
if (hd.ForceLimitPosZ)
{
hd.PreviousZtoRobot = hd.NewZtoRobot;
}
else
{
hd.PreviousZtoRobot = hd.ZtoRobot;
}
strcpy( static_cast<char*>( &acWriteBuffer[0] ), stSend.c_str() );
if (nReadBytes > 0)
{
int nSentBytes = 0;
int SendLength = strlen(acWriteBuffer);
while (nSentBytes < SendLength)
{
int nTemp = sendto(sd, acWriteBuffer, SendLength, 0, (const sockaddr*)&clientAddr, sockAddrSize);
nTempHold = nTemp;
if (nTemp > 0)
{
nSentBytes += nTemp;
}
else if (nTemp == SOCKET_ERROR)
{
return false;
}
else
{
// Client closed connection before we could reply to
// all the data it sent, so bomb out early.
SendDlgItemMessage(g_hWndHapticBox, IDC_LIST_Server, LB_INSERTSTRING, 0, (LPARAM)L"Peer unexpectedly dropped connection!");
return true;
}
}
}
else if (nReadBytes == SOCKET_ERROR)
{
return false;
}
hd.bFirstRunRobot = false;
}while (nReadBytes != 0);
SendDlgItemMessage(g_hWndHapticBox, IDC_LIST_Server, LB_INSERTSTRING, 0, (LPARAM)L"Connection closed by peer.");
bRobotConnected = false;
bRobotConnectInit = true;
SetDlgItemText(g_hWndHapticBox, IDC_STATIC_RobotStatus, _T("Waiting for robot"));
SetDlgItemText(g_hWndHapticBox, IDC_STATIC_RobotInMotion, _T("Robot not in motion"));
return true;
//}
}
And here is the code for the GUI:
// HapticRobot.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "HapticRobot.h"
#include <sstream>
#include <string>
using namespace std;
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE g_hInst; // current instance
HWND g_hWndCommandBar; // command bar handle
HWND g_hWndHapticBox; // haptic dialog handle
bool bRobotInMotion, bRobotConnectInit, bRobotConnected;
extern HapticDevice hd;
HDC hdc;
Handles hc;
DWORD WINAPI DoGravity(LPVOID lpParameter);
DWORD WINAPI DoConnectRobot(LPVOID lpParameter);
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE, LPTSTR);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK HapticBox(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
// Perform application initialization:
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable;
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_HAPTICROBOT));
DialogBox(hInstance, (LPCTSTR)IDD_HAPTIC, NULL, HapticBox);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_HAPTICROBOT));
wc.hCursor = 0;
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = szWindowClass;
return RegisterClass(&wc);
}
//FUNCTION: InitInstance(HINSTANCE, int)
//PURPOSE: Saves instance handle and creates main window
//COMMENTS:
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
TCHAR szTitle[MAX_LOADSTRING]; // title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // main window class name
g_hInst = hInstance; // Store instance handle in our global variable
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_HAPTICROBOT, szWindowClass, MAX_LOADSTRING);
if (!MyRegisterClass(hInstance, szWindowClass))
{
return FALSE;
}
hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
if (g_hWndCommandBar)
{
CommandBar_Show(g_hWndCommandBar, TRUE);
}
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_HELP_ABOUT:
DialogBox(g_hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, About);
break;
case IDM_FILE_EXIT:
dhdClose ();
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_CREATE:
g_hWndCommandBar = CommandBar_Create(g_hInst, hWnd, 1);
CommandBar_InsertMenubar(g_hWndCommandBar, g_hInst, IDR_MENU, 0);
CommandBar_AddAdornments(g_hWndCommandBar, 0, 0);
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
dhdClose ();
CommandBar_Destroy(g_hWndCommandBar);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
RECT rectChild, rectParent;
int DlgWidth, DlgHeight; // dialog width and height in pixel units
int NewPosX, NewPosY;
// trying to center the About dialog
if (GetWindowRect(hDlg, &rectChild))
{
GetClientRect(GetParent(hDlg), &rectParent);
DlgWidth = rectChild.right - rectChild.left;
DlgHeight = rectChild.bottom - rectChild.top ;
NewPosX = (rectParent.right - rectParent.left - DlgWidth) / 2;
NewPosY = (rectParent.bottom - rectParent.top - DlgHeight) / 2;
// if the About box is larger than the physical screen
if (NewPosX < 0) NewPosX = 0;
if (NewPosY < 0) NewPosY = 0;
SetWindowPos(hDlg, 0, NewPosX, NewPosY,
0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
return (INT_PTR)TRUE;
case WM_COMMAND:
if ((LOWORD(wParam) == IDOK) || (LOWORD(wParam) == IDCANCEL))
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
case WM_CLOSE:
EndDialog(hDlg, message);
return TRUE;
}
return (INT_PTR)FALSE;
}
// Message handler for haptic box.
BOOL CALLBACK HapticBox(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
SetWindowPos(hDlg, 0, 130, 200,
0, 0, SWP_NOZORDER | SWP_NOSIZE);
hd.Done = 1;
bRobotInMotion = false;
bRobotConnectInit = false;
g_hWndHapticBox = hDlg;
hd.HapticScaleX = 100;
hd.HapticScaleY = 100;
hd.HapticScaleZ = 100;
hd.MaxForcePos = 160;
hd.MaxForceNeg = -160;
hd.EnableForces = true;
hd.ForceLimitPosX = false;
hd.ForceLimitPosY = false;
hd.ForceLimitPosZ = false;
hd.ForceLimitNegX = false;
hd.ForceLimitNegY = false;
hd.ForceLimitNegZ = false;
hd.filtered_x[0,1,2] = 0; //low pass output for x
hd.filtered_y[0,1,2] = 0; //low pass output for y
hd.filtered_z[0,1,2] = 0; //low pass output for z
hd.raw_x[0,1,2] = 0; //raw haptic data for low pass x
hd.raw_y[0,1,2] = 0; //raw haptic data for low pass y
hd.raw_z[0,1,2] = 0; //raw haptic data for low pass z
hc.Xmm = GetDlgItem(g_hWndHapticBox, IDC_STATIC_X);
hc.Ymm = GetDlgItem(g_hWndHapticBox, IDC_STATIC_Y);
hc.Zmm = GetDlgItem(g_hWndHapticBox, IDC_STATIC_Z);
hc.XtoRobot = GetDlgItem(g_hWndHapticBox, IDC_STATIC_XtoRobot);
hc.YtoRobot = GetDlgItem(g_hWndHapticBox, IDC_STATIC_YtoRobot);
hc.ZtoRobot = GetDlgItem(g_hWndHapticBox, IDC_STATIC_ZtoRobot);
hc.Fx = GetDlgItem(g_hWndHapticBox, IDC_STATIC_Fx);
hc.Fy = GetDlgItem(g_hWndHapticBox, IDC_STATIC_Fy);
hc.Fz = GetDlgItem(g_hWndHapticBox, IDC_STATIC_Fz);
hc.rHz = GetDlgItem(g_hWndHapticBox, IDC_STATIC_Rate);
hc.HapticStatus = GetDlgItem(g_hWndHapticBox, IDC_STATIC_HapticStatus);
hc.RobotInMotion = GetDlgItem(g_hWndHapticBox, IDC_STATIC_RobotInMotion);
hc.RobotStatus = GetDlgItem(g_hWndHapticBox, IDC_STATIC_RobotStatus);
///////////////////////////////////////////////////////////////////////////////////////
hd.HapticConnected = false;
if (hd.HapticConnected == false)
{
DWORD nThreadID;
CreateThread(0, 0, DoConnectRobot, 0, 0, &nThreadID);
Sleep(100);
CreateThread(0, 0, DoGravity, 0, 0, &nThreadID);
hd.HapticConnected = true;
}
return (INT_PTR)TRUE;
case WM_CTLCOLORSTATIC:
if(IDC_STATIC_HapticStatus == ::GetDlgCtrlID((HWND)lParam))
{
hdc = (HDC)wParam;
if (hd.Done == 1)
{
SetBkColor(hdc, RGB(255,0,0)); //red
return (BOOL)::CreateSolidBrush(RGB(255,0,0)); //red
}
else
{
SetBkColor(hdc, RGB(0,255,0)); //green
return (BOOL)::CreateSolidBrush(RGB(0,255,0)); //green
}
}
if(IDC_STATIC_RobotStatus == ::GetDlgCtrlID((HWND)lParam))
{
hdc = (HDC)wParam;
if (bRobotConnectInit)
{
SetBkColor(hdc, RGB(250, 255, 5)); //yellow
return (BOOL)::CreateSolidBrush(RGB(250, 255, 5));
}
else if (bRobotConnected)
{
SetBkColor(hdc, RGB(0,255,0)); //green
return (BOOL)::CreateSolidBrush(RGB(0,255,0));
}
else
{
SetBkColor(hdc, RGB(255,0,0)); //red
return (BOOL)::CreateSolidBrush(RGB(255,0,0));
}
}
if(IDC_STATIC_RobotInMotion == ::GetDlgCtrlID((HWND)lParam))
{
hdc = (HDC)wParam;
if (bRobotInMotion)
{
SetBkColor(hdc, RGB(0,255,0)); //green
return (BOOL)::CreateSolidBrush(RGB(0,255,0));
}
else
{
SetBkColor(hdc, RGB(255,0,0)); //red
return (BOOL)::CreateSolidBrush(RGB(255,0,0));
}
}
break;
case WM_CLOSE:
hd.Done = 1;
EndDialog(hDlg, message);
return TRUE;
}
return (INT_PTR)FALSE;
}
There is more code associated with the solution that if it is need I can attach. My thougt was thought to just call the WM_INITDIALOG case so that basically it would be the same as closing the program out and re opening it. Any suggestions would be appericated.
Callign WM_INITDIALOG definitely won't do what you think it will. Don't send random Windows messages unless you understand them exactly.
My suggestion, given your design, would be to have your program launch another instance of itself and have the old instance exit. Look into CreateProcess on MSDN for the details on how to launch another process. I think that this will be the most maintainable and easy-to-code solution given what you already have.
I would suggest making repeated calls to DialogBox like this:
do
{
DialogBox(hInstance, (LPCTSTR)IDD_HAPTIC, NULL, HapticBox);
} while (ReOpenDialog);
Where ReOpenDialog is a global you set according to the success of your operation (or, to avoid a global, you could use the dialog return result from DialogBox via EndDialog).
Also, you don't need a message loop because DialogBox calls have their own one inside, thus creating a blocking call (which is why my above loop will work, in fact!).
I want to get the primary token so that I can get the access of OpenInputDesktop() and do my necessary things.
I browsed all over the sites for help and found the conclusive code as below but I got an error on calling DuplicateTokenEx() is 998 which means invalid access to memory location.
HANDLE GetCurrentUserToken()
{
HANDLE currentToken = 0;
PHANDLE primaryToken = 0;
unsigned int winlogonPid = 0;
int dwSessionId = 0;
PHANDLE hUserToken = 0;
PHANDLE hTokenDup = 0;
PWTS_SESSION_INFO pSessionInfo = 0;
DWORD dwCount = 0;
WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1,
&pSessionInfo, &dwCount);
//TestLog("Error on WTSEnumerateSessions(): %d",GetLastError());
int dataSize = sizeof(WTS_SESSION_INFO);
for (DWORD i = 0; i < dwCount; ++i)
{
WTS_SESSION_INFO si = pSessionInfo[i];
if (WTSActive == si.State)
{
dwSessionId = si.SessionId;
break;
}
}
WTSFreeMemory(pSessionInfo);
array<Process^>^localByName = Process::GetProcessesByName( "winlogon" );
for (int i=0;i<localByName->Length;i++)
{
Process ^ p1 = (Process^)(localByName->GetValue(i));
if ((unsigned int)p1->SessionId == dwSessionId)
{
winlogonPid = (unsigned int)p1->Id;
}
}
// obtain a handle to the winlogon process
HANDLE hProcess = OpenProcess(MAXIMUM_ALLOWED, false, winlogonPid);
TestLog("Error on OpenProcess():",GetLastError());
// obtain a handle to the access token of the winlogon process
if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE, ¤tToken))
{
TestLog("Error on OpenProcessToken():",GetLastError());
CloseHandle(hProcess);
return false;
}
BOOL bRet ;
// bRet = DuplicateTokenEx(currentToken,
// MAXIMUM_ALLOWED /*TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS*/,
// NULL/*0*/,
// SecurityImpersonation, TokenImpersonation, primaryToken);
bRet = DuplicateTokenEx(currentToken,
TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS,
NULL, SecurityImpersonation,
TokenPrimary, primaryToken);
TestLog("Error on DuplicateTokenEx():",GetLastError());
TestLog("return value of DuplicateTokenEx()",bRet);
int errorcode = GetLastError();
if (bRet == false)
{
return 0;
}
return primaryToken;
}
int main(array<System::String ^> ^args)
{
Console::WriteLine(L"Hello World");
TestLog("**Start TestLaunchExeOneTime**",0);
HANDLE hTokenNew = NULL, hTokenDup = NULL;
HMODULE hmod = LoadLibrary(L"kernel32.dll");
hTokenDup = GetCurrentUserToken();
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si,0,sizeof(STARTUPINFO));
si.cb = sizeof( STARTUPINFO );
si.lpDesktop = L"winsta0\\default";
LPVOID pEnv = NULL;
DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
HMODULE hModule = LoadLibrary(L"Userenv.dll");
if(hModule )
{
if(CreateEnvironmentBlock(&pEnv,hTokenDup,FALSE))
{
//WriteToLog("CreateEnvironmentBlock Ok");
dwCreationFlag |= CREATE_UNICODE_ENVIRONMENT;
}
else
{
TestLog("Error on CreateEnvironmentBlock():",GetLastError());
pEnv = NULL;
}
}
//
if ( !CreateProcessAsUser( hTokenDup,
NULL,
L"C:\\temp\\DesktopDuplicationmilliseconds.exe",
NULL,
NULL,
FALSE,
dwCreationFlag,
pEnv,
NULL,
&si,
&pi
))
{
}
else
{
TestLog("Error on CreateProcessAsUser():",GetLastError());
// printf("error : %d",GetLastError());
}
return 0;
}
You haven't allocated any memory for the primary token. The primaryToken variable is a pointer to a handle, but you haven't actually pointed it to anything. (You've also declared GetCurrentUserToken as a function that returns a handle, but are actually returning a pointer to a handle.)
You need to either explicitly allocate the memory for the handle:
primaryToken = malloc(sizeof(HANDLE));
[...]
return *primaryToken;
or, more sensibly, define primaryToken as a HANDLE rather than a pointer and pass a reference to it in the appropriate place:
HANDLE primaryToken;
[...]
bRet = DuplicateTokenEx(currentToken,
TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS,
NULL, SecurityImpersonation,
TokenPrimary, &primaryToken);
I'm attempting to use the Win32 Raw Input API to collect raw mouse data with higher precision, but I can't seem to make sense of the documentation and samples at all for GetRawInputBuffer.
While my mouse is hovering over the window, nothing seems to happen. I only seem to get buffered data when I click or release on the title bar of the window and even then I mostly get 0 movement values and never receive mouse button changes. I've followed samples as closely as possible and have had little luck searching online.
Below is the the Window Procedure and Main for a heavily simplified example bearing the issue.
LRESULT CALLBACK MessageHandler(HWND WindowHandle, UINT Message, WPARAM wParameter, LPARAM lParameter)
{
switch(Message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
break;
case WM_CLOSE:
{
DestroyWindow(WindowHandle);
return 0;
}
break;
case WM_INPUT:
{
UINT RawInputSize;
UINT Result;
Result = GetRawInputBuffer(NULL, &(RawInputSize), sizeof(RAWINPUTHEADER));
if(Result == -1)
{
DWORD ErrorCode = GetLastError();
std::cout << "GetRawInputBuffer returned error code" << ErrorCode << std::endl;
}
else if(Result == 0 && RawInputSize != 0)
{
UINT AllocatedBufferByteCount = RawInputSize * 16;
RAWINPUT* RawInputBuffer = reinterpret_cast<RAWINPUT*>(malloc(AllocatedBufferByteCount));
UINT AllocatedBufferByteCountTwo = AllocatedBufferByteCount;
Result = GetRawInputBuffer(RawInputBuffer, &(AllocatedBufferByteCountTwo), sizeof(RAWINPUTHEADER));
if(Result == -1)
{
DWORD ErrorCode = GetLastError();
std::cout << "GetRawInputBuffer returned error code" << ErrorCode << std::endl;
}
else if(Result != 0)
{
UINT RawInputCount = Result;
DWORD MouseDeltaX = 0;
DWORD MouseDeltaY = 0;
bool ButtonsPressed[2] = {false, false};
RAWINPUT* RawInput = RawInputBuffer;
for(unsigned int i = 0; i < RawInputCount; ++i)
{
switch(RawInput->header.dwType)
{
// Raw mouse movement data for high-resolution mice.
case RIM_TYPEMOUSE:
{
MouseDeltaX += RawInput->data.mouse.lLastX;
MouseDeltaY += RawInput->data.mouse.lLastY;
ButtonsPressed[0] = ((RawInput->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) == RI_MOUSE_LEFT_BUTTON_DOWN);
ButtonsPressed[1] = ((RawInput->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) == RI_MOUSE_RIGHT_BUTTON_DOWN);
}
break;
}
RawInput = NEXTRAWINPUTBLOCK(RawInput);
}
DefRawInputProc(&(RawInputBuffer), RawInputCount, sizeof(RAWINPUTHEADER));
std::cout << "Mouse moved (" << MouseDeltaX << ", " << MouseDeltaY << ")." << std::endl;
if(ButtonsPressed[0])
{
std::cout << "LMB pressed." << std::endl;
}
if(ButtonsPressed[1])
{
std::cout << "RMB pressed." << std::endl;
}
}
free(RawInputBuffer);
}
return 0;
}
break;
default:
{
return DefWindowProc(WindowHandle, Message, wParameter, lParameter);
}
break;
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
// Initialize window strings.
wchar_t WindowClassName[] = L"DominionWindowClass";
wchar_t WindowCaption[] = L"Test Window";
// Create the window class.
WNDCLASSEX WindowClass;
WindowClass.cbSize = sizeof(WindowClass);
WindowClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
WindowClass.lpfnWndProc = &(MessageHandler);
WindowClass.cbClsExtra = 0;
WindowClass.cbWndExtra = 0;
WindowClass.hInstance = hInstance;
WindowClass.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
WindowClass.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);
WindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WindowClass.hbrBackground = NULL;
WindowClass.lpszMenuName = NULL;
WindowClass.lpszClassName = WindowClassName;
// Register window class.
RegisterClassEx(&WindowClass);
// Setup window style flags.
DWORD WindowStyles = WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU;
DWORD ExWindowStyles = WS_EX_APPWINDOW;
// Setup window rectangle area.
RECT WindowArea;
WindowArea.left = 0;
WindowArea.top = 0;
WindowArea.right = 1024;
WindowArea.bottom = 768;
AdjustWindowRectEx(&(WindowArea), WindowStyles, false, ExWindowStyles);
// Window creation.
HWND WindowHandle = CreateWindowEx(ExWindowStyles, WindowClass.lpszClassName, WindowCaption, WindowStyles, CW_USEDEFAULT, CW_USEDEFAULT, (WindowArea.right - WindowArea.left), (WindowArea.bottom - WindowArea.top), NULL, NULL, hInstance, NULL);
// Display the window.
ShowWindow(WindowHandle, SW_SHOWDEFAULT);
UpdateWindow(WindowHandle);
// Register devices for raw input.
const unsigned int RawInputDeviceCount = 1;
RAWINPUTDEVICE RawInputDevices[RawInputDeviceCount];
memset(RawInputDevices, 0, RawInputDeviceCount * sizeof(RAWINPUTDEVICE));
RAWINPUTDEVICE* MouseRawInputDevice;
MouseRawInputDevice = RawInputDevices;
MouseRawInputDevice->usUsagePage = 1;
MouseRawInputDevice->usUsage = 2;
MouseRawInputDevice->hwndTarget = WindowHandle;
BOOL SuccessfullyRegisteredInput = RegisterRawInputDevices(RawInputDevices, RawInputDeviceCount, sizeof(RAWINPUTDEVICE));
// Core loop.
MSG Message;
for(;;)
{
while(PeekMessage(&Message, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
if(Message.message == WM_QUIT)
{
break;
}
}
if(Message.message == WM_QUIT)
{
break;
}
}
// Unregister devices for raw input.
memset(RawInputDevices, 0, RawInputDeviceCount * sizeof(RAWINPUTDEVICE));
MouseRawInputDevice = RawInputDevices;
MouseRawInputDevice->usUsagePage = 1;
MouseRawInputDevice->usUsage = 2;
MouseRawInputDevice->dwFlags = RIDEV_REMOVE;
MouseRawInputDevice->hwndTarget = NULL;
BOOL SuccessfullyUnregisteredInput = RegisterRawInputDevices(RawInputDevices, RawInputDeviceCount, sizeof(RAWINPUTDEVICE));
return Message.wParam;
}
I can't think of a simpler way to experiment with the Raw Input API. Thoughts?
Long late answer, but GetRawInputBuffer seems to be used for polling outside of the message processing loop. Use GetRawInputData within WM_INPUT handling or use GetRawInputBuffer outside the message processing loop.
I guess with GetRawInputBuffer() you can only read HID data. That means only the hid structure in the data part of the RAWINPUT structure is filled with input data. I was able to read input from my keyboard using the bRawData member of RAWHID but i think thats useless because that values vary from keyboard to keyboard. So I switched back to GetRawInputData....
I'm trying to get an openfile dialog to show up on windows CE 6.0 according to msdn it's the same process as in win32, but it doesn't work. I submit for review the interresting part of the code :
#include <windows.h>
#include <commctrl.h>
#include <winuser.h>
#include <stdio.h>
#include <Commdlg.h>
/* Prototypes */
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HWND create_window(int width, int height) ;
void resize_window(int width, int height) ;
HWND g_hWindow ;
/* Function to modify the host window size to match the size of the movie. */
void resize_window(int width, int height)
{
RECT r;
r.left = r.top = 0;
r.right = width ;
r.bottom = height ;
AdjustWindowRectEx(&r,WS_BORDER,false,WS_EX_CLIENTEDGE);
SetWindowPos(g_hWindow, NULL, 0,0,r.right, r.bottom,SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER);
}
HWND create_window(int width, int height)
{
WNDCLASS wce; // A Window class in Windows CE
wce.style = CS_VREDRAW | CS_HREDRAW;
wce.lpfnWndProc = (WNDPROC) WndProc;
wce.cbClsExtra = 0;
wce.cbWndExtra = 0;
wce.hInstance = GetModuleHandle(NULL);
wce.hIcon = LoadIcon((HINSTANCE) NULL, (LPCWSTR)MB_ICONQUESTION);
wce.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
wce.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wce.lpszMenuName = 0;
wce.lpszClassName = _TEXT("TEST");
if (!RegisterClass(&wce)) return 0;
RECT r;
r.left = r.top = 0;
r.right = width ;
r.bottom = height ;
AdjustWindowRectEx(&r,WS_BORDER,false,WS_EX_CLIENTEDGE);
// Create the window
g_hWindow = CreateWindowEx(
0, // Ex Styles
WS_BORDER, // creates a window that has a thin-line border with no title bar
CW_USEDEFAULT, // x
CW_USEDEFAULT, // y
r.right-r.left, // Height
r.bottom-r.top, // Width
NULL, // Parent Window
NULL, // Menu, or windows id if child
GetModuleHandle(NULL), //
NULL // Pointer to window specific data
);
ShowWindow( g_hWindow, SW_SHOW ); // make the window visible on the display
return g_hWindow ;
}
/*
* Messaging function call back from Windows CE that is passed as
* an argument when the window is created
*/
LRESULT CALLBACK WndProc(HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam )
{
switch( msg )
{
case WM_ACTIVATEAPP:
// Invalidate to get new text painted.
this->Invalidate();
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
LPOPENFILENAME opendialog;
wchar_t szFile[260];
opendialog = (LPOPENFILENAME) malloc(sizeof (LPOPENFILENAME));
opendialog->lStructSize = sizeof (LPOPENFILENAME);
opendialog->hwndOwner = g_hWindow;
opendialog->hInstance = GetModuleHandle(NULL);
*szFile = (char_t)_TEXT("\0");
opendialog->lpstrFile = szFile;
opendialog->nFilterIndex = 0;
opendialog->nMaxFile = 256;
opendialog->lpstrInitialDir = NULL;
opendialog->Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
GetOpenFileName(opendialog);
default:
return DefWindowProc( hWnd, msg, wParam, lParam);
}
return 0;
}
/* Function to hide (or make visible) the taskbar so that the player has the full display */
void set_display(bool set_full)
{
HWND hwndTaskbar = ::FindWindow(L"HHTaskBar", NULL);
if (set_full)
{
::ShowWindow(hwndTaskbar, SW_HIDE);
}
else
{
::ShowWindow(hwndTaskbar, SW_SHOW);
}
g_full_scrn = set_full;
}
int _cdecl WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR argv, int argc )
{
memset(&g_gfx_context,0,sizeof(g_gfx_context));
create_window(1, 1); // This is a windows CE specific call.
}
LPOPENFILENAME opendialog;
mb_char_t szFile[260];
opendialog = (LPOPENFILENAME) mb_malloc(sizeof (LPOPENFILENAME));
opendialog->lStructSize = sizeof (LPOPENFILENAME);
You are declaring a pointer to an OPENFILENAME structure here, and allocating memory for it.
You should be able to allocate OPENFILENAME on stack directly, like so:
OPENFILENAME opendialog = {0};
mb_char_t szFile[260] = {0};
opendialog.lStructSize = sizeof (opendialog);
opendialog.hwndOwner = g_hWindow;
opendialog.hInstance = GetModuleHandle(NULL);
opendialog.lpstrFile = szFile;
opendialog.nFilterIndex = 0;
opendialog.nMaxFile = 256;
opendialog.lpstrInitialDir = NULL;
opendialog.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
GetOpenFileName(&opendialog);
Here's a problem:
opendialog->lStructSize = sizeof (LPOPENFILENAME);
That will set the struct size to the size of a pointer, which is 4 in your case. You should have:
opendialog->lStructSize = sizeof (OPENFILENAME);