Files
argyllcms/usb/ArgyllCMS_uninstall_USB.c
2026-08-20 20:28:40 +01:00

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");
}