251 lines
6.5 KiB
C
251 lines
6.5 KiB
C
|
|
/*
|
|
* Argyll Color Management System
|
|
*
|
|
* Author: Graeme W. Gill
|
|
* Date: 2023/11/16
|
|
*
|
|
* Copyright 2023 Graeme W. Gill
|
|
* All rights reserved.
|
|
*
|
|
* This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
|
|
* see the License2.txt file for licencing details.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include "copyright.h"
|
|
#include "aconfig.h"
|
|
|
|
#include "windows.h"
|
|
#include "setupapi.h"
|
|
|
|
#ifdef SUOI_FORCEDELETE /* If SDK doesn't have declaration... */
|
|
|
|
static void loadSDK() {
|
|
}
|
|
|
|
#else /* If SDK doesn't have declaration... */
|
|
|
|
# define SUOI_FORCEDELETE 0x00000001
|
|
|
|
BOOL (WINAPI *SetupUninstallOEMInfA)(PCSTR FileName, DWORD Flags, PVOID Reserved) = NULL;
|
|
|
|
static void loadSDK() {
|
|
HMODULE dllh = NULL;
|
|
|
|
if ((dllh = LoadLibraryA("Setupapi.dll")) == NULL)
|
|
return;
|
|
|
|
*(FARPROC*)&SetupUninstallOEMInfA = GetProcAddress(dllh, "SetupUninstallOEMInfA");
|
|
}
|
|
|
|
#endif
|
|
|
|
void error(char *fmt, ...), warning(char *fmt, ...);
|
|
|
|
void usage(void) {
|
|
fprintf(stderr,"Uninstall ArgyllCMS libusb-win32 USB drivers%s\n",ARGYLL_VERSION_STR);
|
|
fprintf(stderr,"Author: Graeme W. Gill\n");
|
|
fprintf(stderr,"usage: ArgyllCMS_uninstall_USB [-v level]\n");
|
|
fprintf(stderr," -v level Verbose level 0-2 (default 1)\n");
|
|
exit(1);
|
|
}
|
|
|
|
int
|
|
main(int argc, char *argv[]) {
|
|
int fa,nfa; /* argument we're looking at */
|
|
int verb = 1; /* Default = none */
|
|
int rv = 0;
|
|
|
|
if (argc < 1)
|
|
usage();
|
|
|
|
/* Process the arguments */
|
|
for(fa = 1;fa < argc;fa++) {
|
|
nfa = fa; /* skip to nfa if next argument is used */
|
|
if (argv[fa][0] == '-') { /* Look for any flags */
|
|
char *na = NULL; /* next argument after flag, null if none */
|
|
|
|
if (argv[fa][2] != '\000')
|
|
na = &argv[fa][2]; /* next is directly after flag */
|
|
else {
|
|
if ((fa+1) < argc) {
|
|
if (argv[fa+1][0] != '-') {
|
|
nfa = fa + 1;
|
|
na = argv[nfa]; /* next is seperate non-flag argument */
|
|
}
|
|
}
|
|
}
|
|
|
|
if (argv[fa][1] == '?')
|
|
usage();
|
|
|
|
/* Verbosity */
|
|
else if (argv[fa][1] == 'v') {
|
|
fa = nfa;
|
|
if (na == NULL) usage();
|
|
verb = atoi(na);
|
|
}
|
|
|
|
else
|
|
usage();
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
if (verb >= 1)
|
|
printf("Un-installing ArgyllCMS libusb0 instruments and drivers:\n");
|
|
|
|
/* Un-install Devices */
|
|
{
|
|
// ClassGuid {817cffe0-328b-11df-9b9f-0002a5d5c51b}
|
|
GUID guid = { 0x817cffe0, 0x328b, 0x11df, { 0x9b, 0x9f, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
|
|
HDEVINFO dinfo;
|
|
SP_DEVINFO_DATA infodata = { 0 } ;
|
|
int index = 0;
|
|
|
|
infodata.cbSize = sizeof(SP_DEVINFO_DATA);
|
|
|
|
if ((dinfo = SetupDiGetClassDevsA(&guid, "USB", NULL, 0)) == NULL) {
|
|
error("Didn't find any ArgyllCM libusb0 devices (Error 0x%x)",GetLastError());
|
|
}
|
|
|
|
if (verb >= 2) printf("Un-installing Devices\n");
|
|
|
|
index = 0;
|
|
while (SetupDiEnumDeviceInfo(
|
|
dinfo,
|
|
index,
|
|
&infodata)) {
|
|
int dvix = 0;
|
|
|
|
if (verb >= 2)
|
|
printf("Un-installing device %d, GUID = %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
|
|
index+1,
|
|
infodata.ClassGuid.Data1,
|
|
infodata.ClassGuid.Data2,
|
|
infodata.ClassGuid.Data3,
|
|
infodata.ClassGuid.Data4[0],
|
|
infodata.ClassGuid.Data4[1],
|
|
infodata.ClassGuid.Data4[2],
|
|
infodata.ClassGuid.Data4[3],
|
|
infodata.ClassGuid.Data4[4],
|
|
infodata.ClassGuid.Data4[5],
|
|
infodata.ClassGuid.Data4[6],
|
|
infodata.ClassGuid.Data4[7]);
|
|
|
|
if (!SetupDiCallClassInstaller(DIF_REMOVE, dinfo, &infodata)) {
|
|
if (GetLastError() == 0xe0000235)
|
|
error("Un-installing Device '%d' failed because a 32 bit un-installer won't "
|
|
"work on a 64 bit system.",index+1);
|
|
error("Un-installing Device %d failed (Error 0x%x)",index+1, GetLastError());
|
|
}
|
|
index++;
|
|
}
|
|
SetupDiDestroyDeviceInfoList(dinfo);
|
|
}
|
|
|
|
/* Un-install Driver */
|
|
{
|
|
// ClassGuid {817cffe0-328b-11df-9b9f-0002a5d5c51b}
|
|
GUID guid = { 0x817cffe0, 0x328b, 0x11df, { 0x9b, 0x9f, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
|
|
HDEVINFO dinfo;
|
|
SP_DRVINFO_DATA_A driverinfo = { 0 };
|
|
SP_DRVINFO_DETAIL_DATA_A driverdetail = { 0 };
|
|
CHAR InfName[MAX_PATH], *p;
|
|
DWORD dsize = 0;
|
|
int dvix = 0;
|
|
|
|
driverinfo.cbSize = sizeof(SP_DRVINFO_DATA_A);
|
|
driverdetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_A);
|
|
|
|
if ((dinfo = SetupDiCreateDeviceInfoList(&guid, NULL)) == INVALID_HANDLE_VALUE) {
|
|
error("Creating Device Info failed (Error 0x%x)",GetLastError());
|
|
}
|
|
|
|
if (!SetupDiBuildDriverInfoList(dinfo, NULL, SPDIT_CLASSDRIVER)) {
|
|
error("Failed to locate ArgyllCM libusb0 Driver class (Error 0x%x)",GetLastError());
|
|
}
|
|
|
|
/* Find first device that uses this driver */
|
|
if (!SetupDiEnumDriverInfoA(
|
|
dinfo,
|
|
NULL,
|
|
SPDIT_CLASSDRIVER,
|
|
0,
|
|
&driverinfo)) {
|
|
error("Didn't find any Devices that use the ArgyllCMS driver (Error 0x%x)\n",GetLastError());
|
|
}
|
|
|
|
if (!SetupDiGetDriverInfoDetailA(dinfo, NULL, &driverinfo, &driverdetail,
|
|
driverdetail.cbSize, &dsize) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
|
error("Retrieving detailed Driver information failed (Error 0x%x)\n",GetLastError());
|
|
}
|
|
|
|
if (strlen(driverdetail.InfFileName) > 5
|
|
&& (p = strrchr(driverdetail.InfFileName,'\\')) != NULL) {
|
|
strcpy(InfName, p+1);
|
|
|
|
loadSDK();
|
|
|
|
if (SetupUninstallOEMInfA == NULL)
|
|
error("Couldn't find SetupUninstallOEMInfA API");
|
|
|
|
if (verb >= 1) printf("Un-installing Driver '%s' InfFile '%s'\n",
|
|
driverinfo.ProviderName,InfName);
|
|
|
|
if (!SetupUninstallOEMInfA(InfName, SUOI_FORCEDELETE, NULL)) {
|
|
if (GetLastError() == 0xe0000235)
|
|
error("Un-install driver '%s' failed because a 32 bit un-installer won't "
|
|
"work on a 64 bit system.",driverinfo.ProviderName);
|
|
error("Un-install driver '%s' failed with (Error 0x%x)",
|
|
driverinfo.ProviderName,GetLastError());
|
|
}
|
|
} else {
|
|
error("Driver '%s' InfPath '%s' is invalid\n",
|
|
driverinfo.ProviderName,driverdetail.InfFileName);
|
|
}
|
|
SetupDiDestroyDeviceInfoList(dinfo);
|
|
}
|
|
|
|
if (verb >= 1)
|
|
printf("Un-install success!\n");
|
|
|
|
Sleep(4000); /* Allow message to be read */
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Basic printf type error() and warning() routines */
|
|
|
|
void
|
|
error(char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
|
|
fprintf(stderr," ");
|
|
va_start(args, fmt);
|
|
vfprintf(stderr, fmt, args);
|
|
va_end(args);
|
|
fprintf(stderr, "\n");
|
|
exit (-1);
|
|
}
|
|
|
|
void
|
|
warning(char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
|
|
fprintf(stderr,"Warning - ");
|
|
va_start(args, fmt);
|
|
vfprintf(stderr, fmt, args);
|
|
va_end(args);
|
|
fprintf(stderr, "\n");
|
|
}
|
|
|