639 lines
22 KiB
C
639 lines
22 KiB
C
/*
|
|
Copyright (c) 2013-2014 Anton Titov.
|
|
|
|
Copyright (c) 2013-2014 pCloud Ltd. All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met: Redistributions of source code must retain the above
|
|
copyright notice, this list of conditions and the following
|
|
disclaimer. Redistributions in binary form must reproduce the
|
|
above copyright notice, this list of conditions and the following
|
|
disclaimer in the documentation and/or other materials provided
|
|
with the distribution. Neither the name of pCloud Ltd nor the
|
|
names of its contributors may be used to endorse or promote
|
|
products derived from this software without specific prior written
|
|
permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL pCloud
|
|
Ltd BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
|
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
DAMAGE.
|
|
*/
|
|
|
|
#include "plibs.h"
|
|
#include "psynclib.h"
|
|
//#include "pdevice_monitor.h"
|
|
#include "papi.h"
|
|
#include "pnetlibs.h"
|
|
#include "pbusinessaccount.h"
|
|
#include "pdevicemap.h"
|
|
|
|
#define P_DEVICE_VERBOSE
|
|
|
|
#include "pdevice_monitor.h"
|
|
// #include "pdevicemap.h"
|
|
#include "plocalscan.h"
|
|
#include "ptimer.h"
|
|
|
|
#ifdef P_OS_POSIX
|
|
#define _strdup strdup
|
|
#endif //P_OS_POSIX
|
|
#define DEV_MONITOR_ACTIVITY_TIMER_INT 20
|
|
|
|
static pthread_mutex_t devmon_mutex=PTHREAD_MUTEX_INITIALIZER;
|
|
static psync_timer_t devmon_activity_timer=NULL;
|
|
|
|
void devmon_activity_timer_action(){
|
|
psync_timer_stop(devmon_activity_timer);
|
|
pthread_mutex_lock(&devmon_mutex);
|
|
devmon_activity_timer=NULL;
|
|
pthread_mutex_unlock(&devmon_mutex);
|
|
psync_restat_sync_folders();
|
|
}
|
|
|
|
void devmon_activity_timer_start(){
|
|
pthread_mutex_lock(&devmon_mutex);
|
|
if (!devmon_activity_timer)
|
|
devmon_activity_timer = psync_timer_register(devmon_activity_timer_action, DEV_MONITOR_ACTIVITY_TIMER_INT, NULL);
|
|
pthread_mutex_unlock(&devmon_mutex);
|
|
}
|
|
|
|
//device_event_callback *device_callbacks;
|
|
//int device_clbsize = 10;
|
|
//int device_clbnum = 0;
|
|
|
|
|
|
//void psync_add_device_monitor_callback(device_event_callback callback) {
|
|
// if (callback) {
|
|
// if (device_clbnum == 0)
|
|
// device_callbacks = (device_event_callback *)psync_malloc(sizeof(device_event_callback)*device_clbsize);
|
|
// else {
|
|
// while (device_clbnum > device_clbsize) {
|
|
// device_event_callback *callbacks_old = device_callbacks;
|
|
// device_callbacks = (device_event_callback *)psync_malloc(sizeof(device_event_callback)*device_clbsize*2);
|
|
// memccpy(device_callbacks, callbacks_old, 0,sizeof(device_event_callback)*device_clbsize);
|
|
// device_clbsize = device_clbsize * 2;
|
|
// psync_free(callbacks_old);
|
|
// }
|
|
// }
|
|
// device_callbacks[device_clbnum] = callback;
|
|
// device_clbnum
|
|
// ++;
|
|
// }
|
|
//}
|
|
|
|
|
|
// static pdevice_info * new_dev_info( char *szPath, pdevice_types type, device_event evt) {
|
|
// /*int pathsize = strlen(szPath);
|
|
// int infstrsize = sizeof(pdevice_info);
|
|
// int infsize = pathsize + infstrsize + 1;*/
|
|
// // pdevice_info *infop = (pdevice_info *)psync_malloc(infsize);
|
|
// pdevice_info *infop = (pdevice_info *)psync_malloc(sizeof(pdevice_info));
|
|
// //ZeroMemory(infop, infsize);
|
|
// //infop->filesystem_path = (char *)(infop) + infstrsize;
|
|
// infop->filesystem_path = strdup(szPath);
|
|
// //memcpy(infop->filesystem_path, szPath, pathsize);
|
|
// //infop->filesystem_path[pathsize] = '\0';
|
|
// infop->type = type;
|
|
// infop->isextended = 0;
|
|
// return infop;
|
|
// }
|
|
|
|
|
|
// static pdevice_extended_info * new_dev_ext_info(char *szPath, char * vendor, char *product, char* deviceid, pdevice_types type, device_event evt) {
|
|
// /*uint32_t pathsize = strlen(szPath);
|
|
// uint32_t vndsize = strlen(vendor);
|
|
// uint32_t prdsize = strlen(product);
|
|
// uint32_t devsize = strlen(deviceid);
|
|
// uint32_t infstrsize = sizeof(pdevice_extended_info);
|
|
// uint32_t infsize = pathsize + infstrsize + pathsize + vndsize + prdsize + 5;
|
|
// void * infovp = psync_malloc(infsize);
|
|
// pdevice_extended_info *infop = (pdevice_extended_info *)infovp;
|
|
// ZeroMemory(infop, infsize);
|
|
// char *storage_begin = (char *)(infovp)+infstrsize;
|
|
// put_into_storage(&infop->filesystem_path, &storage_begin, szPath, pathsize);
|
|
// put_into_storage(&infop->vendor, &storage_begin, vendor, vndsize);
|
|
// put_into_storage(&infop->product, &storage_begin, product, prdsize);
|
|
// put_into_storage(&infop->device_id, &storage_begin, deviceid, devsize);
|
|
// infop->type = type;
|
|
// infop->event = evt;
|
|
// infop->isextended = 1;
|
|
// infop->size = infsize;
|
|
// infop->me = infop;*/
|
|
// pdevice_extended_info *infop = (pdevice_extended_info *)psync_malloc(sizeof(pdevice_extended_info));
|
|
// infop->filesystem_path = strdup(szPath);
|
|
// infop->vendor = strdup(vendor);
|
|
// infop->product = strdup(product);
|
|
// infop->device_id = strdup(deviceid);
|
|
// infop->type = type;
|
|
// infop->isextended = 1;
|
|
// return infop;
|
|
// }
|
|
|
|
|
|
//void psync_devmon_notify_device_callbacks(pdevice_extended_info * param, device_event event) {
|
|
// if (event == Dev_Event_arrival)
|
|
// psync_run_thread1("Device notifications", do_notify_device_callbacks_in, (void*)param);
|
|
// else
|
|
// psync_run_thread1("Device notifications", do_notify_device_callbacks_out, (void*)param);
|
|
//}
|
|
|
|
//static void psync_devmon_arivalmonitor(device_event event, void * device_info)
|
|
//{
|
|
// pdevice_extended_info *pDevExtInfo = (pdevice_extended_info*)device_info;
|
|
// if (event == Dev_Event_arrival){
|
|
// debug(D_NOTICE, "Device arrived.");
|
|
// psync_do_restat_sync_folders();
|
|
// }
|
|
// else{
|
|
// debug(D_NOTICE, "Device removed.");
|
|
// psync_do_restat_sync_folders();
|
|
// }
|
|
// if (pDevExtInfo)
|
|
// print_device_info(pDevExtInfo);
|
|
//}
|
|
|
|
#ifdef P_OS_MACOSX
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <CoreFoundation/CoreFoundation.h>
|
|
#include <IOKit/IOKitLib.h>
|
|
#include <IOKit/IOMessage.h>
|
|
#include <IOKit/IOCFPlugIn.h>
|
|
#include <IOKit/usb/IOUSBLib.h>
|
|
|
|
typedef struct MyPrivateData {
|
|
io_object_t notification;
|
|
const char* systempath;
|
|
} MyPrivateData;
|
|
|
|
static IONotificationPortRef gNotifyPort;
|
|
static io_iterator_t gAddedIter;
|
|
static CFRunLoopRef gRunLoop;
|
|
|
|
void DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument)
|
|
{
|
|
kern_return_t kr;
|
|
MyPrivateData *privateDataRef = (MyPrivateData *) refCon;
|
|
|
|
if (messageType == kIOMessageServiceIsTerminated) {
|
|
// remove_device(privateDataRef->systempath);
|
|
// debug(D_NOTICE, "Device removed. Mountpoint: %s\n", privateDataRef->systempath);
|
|
free(privateDataRef->systempath);
|
|
kr = IOObjectRelease(privateDataRef->notification);
|
|
free(privateDataRef);
|
|
devmon_activity_timer_start();
|
|
}
|
|
}
|
|
|
|
void DeviceAdded(void *refCon, io_iterator_t iterator)
|
|
{
|
|
kern_return_t kr;
|
|
io_service_t usbDevice;
|
|
CFStringRef deviceNameAsCFString;
|
|
static int first_call=1;
|
|
|
|
while ((usbDevice = IOIteratorNext(iterator))) {
|
|
io_name_t deviceName;
|
|
MyPrivateData *privateDataRef = NULL;
|
|
privateDataRef = malloc(sizeof(MyPrivateData));
|
|
bzero(privateDataRef, sizeof(MyPrivateData));
|
|
// Ought to work now, regardless of version of OSX being ran.
|
|
CFStringRef usbSerial = (CFStringRef) IORegistryEntrySearchCFProperty(
|
|
usbDevice,
|
|
kIOServicePlane,
|
|
CFSTR("USB Serial Number"),
|
|
kCFAllocatorDefault,
|
|
kIORegistryIterateRecursively
|
|
);
|
|
// if (!usbSerial) continue;
|
|
// Ought to work now, regardless of version of OSX being ran.
|
|
CFStringRef usbVendor = (CFStringRef) IORegistryEntrySearchCFProperty(
|
|
usbDevice,
|
|
kIOServicePlane,
|
|
CFSTR("USB Vendor Name"),
|
|
kCFAllocatorDefault,
|
|
kIORegistryIterateRecursively
|
|
);
|
|
// if (!usbVendor) continue;
|
|
// Get the USB device's name.
|
|
kr = IORegistryEntryGetName(usbDevice, deviceName);
|
|
if (KERN_SUCCESS != kr) {
|
|
deviceName[0] = '\0';
|
|
}
|
|
deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, deviceName,
|
|
kCFStringEncodingASCII);
|
|
// if (!deviceNameAsCFString) continue;
|
|
if (!first_call){
|
|
debug(D_NOTICE, "start deviceactivity timer");
|
|
devmon_activity_timer_start();
|
|
}
|
|
// Register for an interest notification of this device being removed. Use a reference to our
|
|
// private data as the refCon which will be passed to the notification callback.
|
|
kr = IOServiceAddInterestNotification(gNotifyPort, // notifyPort
|
|
usbDevice, // service
|
|
kIOGeneralInterest, // interestType
|
|
DeviceNotification, // callback
|
|
privateDataRef, // refCon
|
|
&(privateDataRef->notification) // notification
|
|
);
|
|
if (KERN_SUCCESS != kr) {
|
|
debug(D_NOTICE, "IOServiceAddInterestNotification returned 0x%08x.\n", kr);
|
|
}
|
|
// Done with this USB device; release the reference added by IOIteratorNext
|
|
kr = IOObjectRelease(usbDevice);
|
|
}
|
|
first_call=0;
|
|
}
|
|
|
|
void device_monitor_thread() {
|
|
CFMutableDictionaryRef matchingDict;
|
|
CFRunLoopSourceRef runLoopSource;
|
|
// CFNumberRef numberRef;
|
|
kern_return_t kr;
|
|
matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class
|
|
// IOUSBDevice and its subclasses
|
|
if (matchingDict == NULL) {
|
|
debug(D_NOTICE, "IOServiceMatching returned NULL.\n");
|
|
return;
|
|
}
|
|
gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault);
|
|
runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort);
|
|
gRunLoop = CFRunLoopGetCurrent();
|
|
CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode);
|
|
// Now set up a notification to be called when a device is first matched by I/O Kit.
|
|
kr = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort
|
|
kIOFirstMatchNotification, // notificationType
|
|
matchingDict, // matching
|
|
DeviceAdded, // callback
|
|
NULL, // refCon
|
|
&gAddedIter // notification
|
|
);
|
|
// Iterate once to get already-present devices and arm the notification
|
|
DeviceAdded(NULL, gAddedIter);
|
|
// Start the run loop. Now we'll receive notifications.
|
|
debug(D_NOTICE, "Starting run loop.\n\n");
|
|
CFRunLoopRun();
|
|
// We should never get here
|
|
debug(D_NOTICE, "Unexpectedly back from CFRunLoopRun()!");
|
|
return;
|
|
}
|
|
|
|
void psync_devmon_init(){
|
|
psync_run_thread("Device monitor main thread", device_monitor_thread);
|
|
}
|
|
#endif //P_OS_MACOSX
|
|
|
|
#ifdef P_OS_LINUX
|
|
#include <libudev.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <locale.h>
|
|
#include <unistd.h>
|
|
|
|
|
|
void enumerate_devices (struct udev *udev,device_event event) {
|
|
devmon_activity_timer_start();
|
|
}
|
|
|
|
void monitor_usb_dev(){
|
|
struct udev *udev;
|
|
struct udev_device *dev;
|
|
struct udev_monitor *mon;
|
|
int fd;
|
|
|
|
udev = udev_new();
|
|
if (!udev) {
|
|
debug(D_WARNING, "Can't create udev\n");
|
|
return;
|
|
}
|
|
mon = udev_monitor_new_from_netlink(udev, "udev");
|
|
udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", NULL);
|
|
udev_monitor_enable_receiving(mon);
|
|
/* Get the file descriptor (fd) for the monitor.
|
|
This fd will get passed to select() */
|
|
fd = udev_monitor_get_fd(mon);
|
|
while (1) {
|
|
/* Set up the call to select(). In this case, select() will
|
|
only operate on a single file descriptor, the one
|
|
associated with our udev_monitor. Note that the timeval
|
|
object is set to 0, which will cause select() to not
|
|
block. */
|
|
fd_set fds;
|
|
struct timeval tv;
|
|
int ret;
|
|
FD_ZERO(&fds);
|
|
FD_SET(fd, &fds);
|
|
tv.tv_sec = 0;
|
|
tv.tv_usec = 0;
|
|
ret = select(fd+1, &fds, NULL, NULL, &tv);
|
|
/* Check if our file descriptor has received data. */
|
|
if (ret > 0 && FD_ISSET(fd, &fds)){
|
|
|
|
/* Make the call to receive the device.
|
|
select() ensured that this will not block. */
|
|
dev = udev_monitor_receive_device(mon);
|
|
if (dev) {
|
|
enumerate_devices(udev, Dev_Event_arrival);
|
|
}
|
|
else {
|
|
// printf("No Device from receive_device(). An error occured.\n");
|
|
}
|
|
}
|
|
usleep(250*1000);
|
|
fflush(stdout);
|
|
}
|
|
udev_unref(udev);
|
|
return;
|
|
}
|
|
|
|
void device_monitor_thread(){
|
|
debug(D_NOTICE, "Waiting for USB devices connect/disconnect events");
|
|
monitor_usb_dev();
|
|
}
|
|
|
|
void psync_devmon_init(){
|
|
psync_run_thread("libusb handle events completed thread", device_monitor_thread);
|
|
}
|
|
#endif //P_OS_LINUX
|
|
|
|
#ifdef P_OS_WINDOWS
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#define _WIN32_WINNT 0x0601
|
|
|
|
#include <windows.h>
|
|
#include <dbt.h>
|
|
#include <shlobj.h>
|
|
#include <shobjidl.h>
|
|
#include <strsafe.h>
|
|
#include <shlwapi.h>
|
|
#include <winioctl.h>
|
|
|
|
#define CLS_NAME "DUMMY_CLASS"
|
|
#define HWND_MESSAGE ((HWND)-3)
|
|
#define WM_USER_MEDIACHANGED WM_USER+88
|
|
#define MAX_LOADSTRING 100
|
|
|
|
static GUID WusbGUID = { 0x88BAE032, 0x5A81, 0x49f0, 0xBC,0x3D,0xA4,0xFF,0x13,0x82,0x16,0xD6 };
|
|
static HDEVNOTIFY hDeviceNotify;
|
|
static HWND hWnd = NULL;
|
|
|
|
static pdevice_types dev_decode_type(STORAGE_BUS_TYPE bustype, DWORD drivetype) {
|
|
switch (bustype) {
|
|
case BusTypeScsi:
|
|
case BusTypeiScsi:
|
|
case BusTypeUsb:
|
|
case BusTypeSata:
|
|
if (drivetype == DRIVE_REMOVABLE)
|
|
return Dev_Types_UsbRemovableDisk;
|
|
else
|
|
return Dev_Types_UsbFixedDisk;
|
|
break;
|
|
case BusTypeSd:
|
|
return Dev_Types_AndroidDevice;
|
|
break;
|
|
case BusTypeMmc:
|
|
return Dev_Types_CameraDevice;
|
|
default:
|
|
return Dev_Types_Unknown;
|
|
}
|
|
}
|
|
|
|
BOOL DoRegisterDeviceInterfaceToHwnd(
|
|
IN GUID InterfaceClassGuid,
|
|
IN HWND hWnd,
|
|
OUT HDEVNOTIFY *hDeviceNotify
|
|
)
|
|
{
|
|
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
|
|
ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
|
|
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
|
|
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; //DBT_DEVTYP_DEVICEINTERFACE, DBT_DEVTYP_DEVNODE, DBT_DEVTYP_OEM, DBT_DEVTYP_VOLUME;
|
|
NotificationFilter.dbcc_classguid = InterfaceClassGuid;
|
|
*hDeviceNotify = RegisterDeviceNotification(
|
|
hWnd, // events recipient
|
|
&NotificationFilter, // type of device
|
|
DEVICE_NOTIFY_WINDOW_HANDLE|DEVICE_NOTIFY_ALL_INTERFACE_CLASSES // type of recipient handle
|
|
);
|
|
if (NULL == *hDeviceNotify){
|
|
debug(D_NOTICE, "RegisterDeviceNotification failed");
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static DWORD GetPhysicalDriveParams(char *strdrivepath IN, DWORD drivetype, char *fspath)
|
|
{
|
|
DWORD dwRet = NO_ERROR;
|
|
STORAGE_PROPERTY_QUERY storagePropertyQuery;
|
|
|
|
HANDLE hDevice = CreateFileA(strdrivepath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
|
|
|
if (INVALID_HANDLE_VALUE == hDevice) {
|
|
return GetLastError();
|
|
}
|
|
|
|
ZeroMemory(&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY));
|
|
storagePropertyQuery.PropertyId = StorageDeviceProperty;
|
|
storagePropertyQuery.QueryType = PropertyStandardQuery;
|
|
STORAGE_DESCRIPTOR_HEADER storageDescriptorHeader = { 0 };
|
|
DWORD dwBytesReturned = 0;
|
|
if (!DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
|
|
&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY),
|
|
&storageDescriptorHeader, sizeof(STORAGE_DESCRIPTOR_HEADER),
|
|
&dwBytesReturned, NULL)){
|
|
dwRet = GetLastError();
|
|
CloseHandle(hDevice);
|
|
return dwRet;
|
|
}
|
|
// Alloc the output buffer
|
|
const DWORD dwOutBufferSize = storageDescriptorHeader.Size;
|
|
BYTE* pOutBuffer = (BYTE*)psync_malloc(dwOutBufferSize);
|
|
ZeroMemory(pOutBuffer, dwOutBufferSize);
|
|
// Get the storage device descriptor
|
|
if (!DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
|
|
&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY),
|
|
pOutBuffer, dwOutBufferSize,
|
|
&dwBytesReturned, NULL))
|
|
{
|
|
dwRet = GetLastError();
|
|
free(pOutBuffer);
|
|
CloseHandle(hDevice);
|
|
return dwRet;
|
|
}
|
|
STORAGE_DEVICE_DESCRIPTOR* pDeviceDescriptor = (STORAGE_DEVICE_DESCRIPTOR*)pOutBuffer;
|
|
free (pOutBuffer);
|
|
CloseHandle(hDevice);
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
typedef struct {
|
|
DWORD dwItem1; // dwItem1 contains the previous PIDL or name of the folder.
|
|
DWORD dwItem2; // dwItem2 contains the new PIDL or name of the folder.
|
|
} SHNOTIFYSTRUCT;
|
|
|
|
static LRESULT message_handler(HWND *hwnd, UINT uint, WPARAM wparam, LPARAM lparam)
|
|
{
|
|
switch (uint)
|
|
{
|
|
case WM_NCCREATE:
|
|
return 1;
|
|
break;
|
|
case WM_CREATE:
|
|
return 0;
|
|
break;
|
|
case WM_DEVICECHANGE:
|
|
devmon_activity_timer_start();
|
|
//switch (wparam)
|
|
//{
|
|
//case DBT_DEVICEARRIVAL:
|
|
// debug(D_NOTICE, "Message %d: DBT_DEVICEARRIVAL\n");
|
|
// break;
|
|
//case DBT_DEVICEREMOVECOMPLETE:
|
|
// debug(D_NOTICE, "Message %d: DBT_DEVICEREMOVECOMPLETE\n");
|
|
// break;
|
|
//case DBT_DEVNODES_CHANGED:
|
|
// debug(D_NOTICE, "Message %d: DBT_DEVNODES_CHANGED\n");
|
|
// break;
|
|
//default:
|
|
// debug(D_NOTICE, "Message %d: WM_DEVICECHANGE message received, value %d unhandled.\n");
|
|
//break;
|
|
//}
|
|
break;
|
|
case WM_USER_MEDIACHANGED:
|
|
{
|
|
SHNOTIFYSTRUCT *shns = (SHNOTIFYSTRUCT *)wparam;
|
|
char szPath[MAX_PATH];
|
|
ZeroMemory(&szPath, MAX_PATH);
|
|
switch (lparam)
|
|
{
|
|
case SHCNE_MEDIAINSERTED: // media inserted event
|
|
{
|
|
devmon_activity_timer_start();
|
|
break;
|
|
}
|
|
case SHCNE_MEDIAREMOVED: // media removed event
|
|
{
|
|
SHGetPathFromIDListA((struct _ITEMIDLIST *)shns->dwItem1, szPath);
|
|
devmon_activity_timer_start();
|
|
break;
|
|
}
|
|
case SHCNE_DRIVEADD: // media added event
|
|
{
|
|
DWORD drivetype;
|
|
HANDLE hDevice;
|
|
PSTORAGE_DEVICE_DESCRIPTOR pDevDesc;
|
|
SHGetPathFromIDListA((struct _ITEMIDLIST *)shns->dwItem1, szPath);
|
|
// "X:\" -> for GetDriveType
|
|
char szRootPath[] = "X:\\";
|
|
szRootPath[0] = szPath[0];
|
|
// "X:" -> for QueryDosDevice
|
|
char szDevicePath[] = "X:";
|
|
szDevicePath[0] = szPath[0];
|
|
// "\\.\X:" -> to open the volume
|
|
char szVolumeAccessPath[] = "\\\\.\\X:";
|
|
szVolumeAccessPath[4] = szPath[0];
|
|
drivetype = GetDriveTypeA(szRootPath);
|
|
switch (drivetype)
|
|
{
|
|
case 0: // The drive type cannot be determined.
|
|
debug(D_NOTICE, "The drive type cannot be determined!");
|
|
break;
|
|
case 1: // The root directory does not exist.
|
|
debug(D_NOTICE, "The root directory does not exist!");
|
|
break;
|
|
case DRIVE_CDROM: // The drive is a CD-ROM drive.
|
|
debug(D_NOTICE, "The drive is a CD-ROM drive.");
|
|
case DRIVE_REMOVABLE: // The drive can be removed from the drive.
|
|
case DRIVE_FIXED: // The disk cannot be removed from the drive.
|
|
case DRIVE_REMOTE: // The drive is a remote (network) drive.
|
|
devmon_activity_timer_start();
|
|
break;
|
|
case DRIVE_RAMDISK: // The drive is a RAM disk.
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case SHCNE_DRIVEREMOVED: // media removed event
|
|
{
|
|
DWORD drivetype;
|
|
SHGetPathFromIDListA((struct _ITEMIDLIST *)shns->dwItem1, szPath);
|
|
drivetype = GetDriveTypeA(szPath);
|
|
devmon_activity_timer_start();
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
void device_monitor_thread() {
|
|
WNDCLASSEXA wx;
|
|
// debug_execute(D_NOTICE, psync_add_device_monitor_callback(psync_devmon_arivalmonitor));
|
|
HINSTANCE hExe = GetModuleHandleA(0);
|
|
ZeroMemory(&wx, sizeof(wx));
|
|
wx.cbSize = sizeof(WNDCLASSEXA);
|
|
wx.lpfnWndProc = (WNDPROC) (message_handler);
|
|
wx.hInstance = (HINSTANCE) (hExe);
|
|
wx.style = CS_HREDRAW|CS_VREDRAW;
|
|
wx.hbrBackground = (HBRUSH)(COLOR_WINDOW);
|
|
wx.lpszClassName = CLS_NAME;
|
|
if (RegisterClassExA(&wx)){
|
|
hWnd=CreateWindowA(CLS_NAME, L"DevNotifWnd", WS_ICONIC, 0, 0,
|
|
CW_USEDEFAULT, 0, HWND_MESSAGE, NULL, hExe, NULL);
|
|
}
|
|
if (hWnd==NULL){
|
|
debug(D_ERROR, "Could not create message window. Error: %d", GetLastError());
|
|
return;
|
|
}
|
|
if (!DoRegisterDeviceInterfaceToHwnd(WusbGUID, hWnd, &hDeviceNotify)){
|
|
debug(D_ERROR, "DoRegisterDeviceInterfaceToHwnd failed. Error: %d", GetLastError());
|
|
return;
|
|
}
|
|
//ULONG m_ulSHChangeNotifyRegister;
|
|
//LPITEMIDLIST ppidl;
|
|
//if (SHGetSpecialFolderLocation(hWnd, CSIDL_DESKTOP, &ppidl) == NOERROR)
|
|
//{
|
|
// SHChangeNotifyEntry shCNE;
|
|
// shCNE.pidl = ppidl;
|
|
// shCNE.fRecursive = TRUE;
|
|
// m_ulSHChangeNotifyRegister = SHChangeNotifyRegister(hWnd,
|
|
// SHCNE_DISKEVENTS,
|
|
// SHCNE_MEDIAINSERTED | SHCNE_MEDIAREMOVED | SHCNE_DRIVEREMOVED | SHCNE_DRIVEADD,
|
|
// WM_USER_MEDIACHANGED,
|
|
// 1,
|
|
// &shCNE);
|
|
// if (m_ulSHChangeNotifyRegister == 0) {
|
|
// debug(D_NOTICE, "Shell Device Notify registration CD failed with error %d", GetLastError());
|
|
// return 2;
|
|
// }
|
|
//}
|
|
//else
|
|
// debug(D_NOTICE, "Shell Device Notify registration CD failed with error %d ", GetLastError());
|
|
debug(D_NOTICE, "Device monitor - waiting for device arrival/removal");
|
|
MSG msg;
|
|
while (GetMessage(&msg, NULL, 0, 0)){
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
void psync_devmon_init(){
|
|
psync_run_thread("Device monitor main thread", device_monitor_thread);
|
|
}
|
|
#endif //P_OS_WINDOWS
|