Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1160 lines
39 KiB

#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <winspool.h>
//#include <wchar.h>
#include <setupapi.h>
//#include <stdlib.h>
#include "enumports.h"
#include "usbmon.h"
void vOldAddItemToPortList(PUSBMON_PORT_INFO *pHead,PUSBMON_PORT_INFO pNew);
PUSBMON_PRINTER_INFO pOldGetPrinterList();
LONG UpdateAssociations(PUSBMON_PORT_INFO *ppPortList,PUSBMON_PRINTER_INFO pPrinterList);
LONG AllocateNewPorts(PUSBMON_PORT_INFO *ppPortList,PUSBMON_PRINTER_INFO pPrinterList);
LONG DoBestEffortMatches(PUSBMON_PORT_INFO pPortList,PUSBMON_PRINTER_INFO pPrinterList);
LONG ReattachExactMatches(PUSBMON_PORT_INFO pPortList,PUSBMON_PRINTER_INFO pPrinterList);
//void InitPortBits(PUSBMON_PORT_INFO pPortList);
//PUSBMON_PORT_INFO pGetNewPortNode(PUSBMON_PORT_INFO *ppListHead);
LONG WriteNewAssociations(int *iNumberOfPorts,PUSBMON_PORT_INFO pPortList,HKEY hPortRoot);
void FreePrinterList(PUSBMON_PRINTER_INFO pPrinterList);
LONG BuildReturnTable(int iNumberOfPorts,PUSBMON_PORT_INFO pPortList,DWORD Level,LPBYTE Ports,DWORD cBuf,LPDWORD pcbNeeded,LPDWORD pcReturned);
char szDebugBuff[512];
char *WtoA(WCHAR *pInString);
long lAddPrinterToList(PUSBMON_PORT_INFO *ppHead,HDEVINFO hDeviceList,PSP_DEVICE_INTERFACE_DATA prDeviceInfo,PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceDetail,PUSBMON_BASENAME *ppBaseNames);
int iCountPresentPrinters(PUSBMON_PORT_INFO pHead);
LONG lGetPrintersAndPorts(PUSBMON_PORT_INFO *ppHead,PUSBMON_BASENAME *);
LONG lGetQueues(PUSBMON_QUEUE_INFO *ppQueueList,PUSBMON_BASENAME pBaseNames);
LONG lAddQueueToList(LPWSTR pPortName,LPWSTR pPrinterName,PUSBMON_QUEUE_INFO *ppQueueHead);
void vDestroyQueueList(PUSBMON_QUEUE_INFO pQueueList);
void vCleanUpQueuesAndPorts(PUSBMON_PORT_INFO * pPortInfo,int iNumberOfPorts,PUSBMON_BASENAME pBaseNames);
DWORD WINAPI CleanupThread(LPVOID pParam);
void vEliminateOldQueuesAndPorts(PUSBMON_QUEUE_INFO pQueueInfo,PUSBMON_PORT_INFO * fpPortInfo);
void vDeletePort(PUSBMON_PORT_INFO pPort, HDEVINFO hDeviceList);
void vGreyOutQueue(PUSBMON_QUEUE_INFO pQueue);
void vUnGreyQueue(PUSBMON_QUEUE_INFO pQueue);
HANDLE hGetPortRegKey(PUSBMON_PORT_INFO pPort, HDEVINFO hDeviceList);
void vAddNameToBaseNameList(PUSBMON_BASENAME *ppBaseNames,WCHAR *wcPortBaseName);
BOOL bCheckPortName(LPTSTR pPortName,PUSBMON_BASENAME pBaseNames);
int iGetNumberOfPorts(PUSBMON_PORT_INFO pHead);
int iCleanupThreads=0;
HKEY hPortsKeyG; //global
PUSBMON_PORT_INFO pPortInfoG=NULL;
int iLastPrintersHere=-1;
typedef struct CLEANUP_THREAD_PARAMS_DEF
{
PUSBMON_PORT_INFO * ppPortInfo;
PUSBMON_BASENAME pBaseNames;
int iPortCount;
HANDLE hSemaphore;
} CLEANUP_THREAD_PARAMS,*PCLEANUP_THREAD_PARAMS;
BOOL WINAPI USBMON_EnumPorts(LPWSTR pName, DWORD Level, LPBYTE pPorts, DWORD cbBuf,LPDWORD pcbNeeded, LPDWORD pcReturned)
{
PUSBMON_PRINTER_INFO pPrinterList;
LONG lResult;
DWORD dwStatus;
int iNumberOfPorts;
static int iOldNumberOfPorts=0;
static int iNumCalls=0;
int iThisCall;
int iPrintersHere;
OutputDebugStringD2("USBMON ++=Head of EnumPorts, before WaitForSingleObject\n");
iThisCall=++iNumCalls;
wsprintfA(szDebugBuff,"USBMON: +++++++++++++++++++++++++++++++++++++++++++++++++EnumPorts call # %d, handle = %x\n",iThisCall,hMonitorSemaphore);
OutputDebugStringD2(szDebugBuff);
dwStatus=WaitForSingleObject(hMonitorSemaphore,INFINITE);
if(dwStatus==WAIT_FAILED)
{
OutputDebugStringD1("USBMON: WaitForSingleObject failed!\n");
}
wsprintfA(szDebugBuff,"USBMON Head of EnumPrts, ++++++++++++++++++++++++++++++++++++ Instance # %d, after WaitForSingleObject, return code=%d\n",iThisCall,dwStatus);
OutputDebugStringD2(szDebugBuff);
lResult=lGetPrintersAndPorts(&pPortInfoG,&GpBaseNameList);
iNumberOfPorts=iGetNumberOfPorts(pPortInfoG);
if(iCleanupThreads==0)
{
iPrintersHere=iCountPresentPrinters(pPortInfoG);
if(iPrintersHere!=iLastPrintersHere)
{
iLastPrintersHere=iPrintersHere;
iCleanupThreads++;
OutputDebugStringD3("USBMON: About to clean up queues and ports\n");
vCleanUpQueuesAndPorts(&pPortInfoG,iNumberOfPorts,GpBaseNameList);
} //end printer count changed
}
lResult=BuildReturnTable(iNumberOfPorts,pPortInfoG,Level,pPorts,cbBuf,pcbNeeded,pcReturned);
if(lResult!=ERROR_SUCCESS)
{
OutputDebugStringD2("USBMON: Unable to build return buffer (this is normal for first call)\n");
goto EnumPortsError;
}
OutputDebugStringD3("USBMON tail of EnumPorts, before ReleaseSemaphore\n");
ReleaseSemaphore(hMonitorSemaphore,1,NULL);
return TRUE;
EnumPortsError:
wsprintfA(szDebugBuff,"USBMON tail of EnumPorts, error path, before ReleaseSemaphore, *pcbNeeded=%d\n",*pcbNeeded);
OutputDebugStringD3(szDebugBuff);
if(!ReleaseSemaphore(hMonitorSemaphore,1,NULL))
{
wsprintfA(szDebugBuff,"USBMON: EnumPorts Release sempahore failed for instance %d \n",iThisCall);
OutputDebugStringD1(szDebugBuff);
}
else
{
wsprintfA(szDebugBuff,"USBMON: EnumPortsRelease sempahore succeeded for instance %d \n",iThisCall);
OutputDebugStringD2(szDebugBuff);
}
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
} /*End EnumPorts*/
int iGetNumberOfPorts(PUSBMON_PORT_INFO pHead)
{
PUSBMON_PORT_INFO pWalk;
int iCount=0;
pWalk=pHead;
while(pWalk!=NULL)
{
iCount++;
pWalk=pWalk->pNext;
}/*end while*/
return iCount;
} /*end function iGetNumberOfPorts*/
/***********************************
* lGetQueues
*
* This function builds a linked list of print queues
* who's port names start with a registered basename.
*
* This list is used to grey out queues who's printers are
* Unavailable, and to delete ports who's printers are gone
************************************************************/
LONG lGetQueues(PUSBMON_QUEUE_INFO *ppQueueList,PUSBMON_BASENAME pBaseNames)
{
DWORD dwBufferSize=1024;
DWORD dwBufferNeeded=0;
DWORD dwNumStructs;
LPBYTE lpBuffer;
BOOL bStatus;
DWORD dwLoop;
PRINTER_INFO_5 *pEnumInfo;
LONG lStatus;
OutputDebugStringD2("USBMON: Head of lGetQueues \n");
lpBuffer=(LPBYTE)GlobalAlloc(0,dwBufferSize);
if(lpBuffer==NULL)
{
OutputDebugStringD1("USBMON: Unable to allocate memory in lGetQueues\n");
return ERROR_NOT_ENOUGH_MEMORY;
}
OutputDebugStringD3("USBMON: Before EnumPrinters \n");
bStatus=EnumPrinters(PRINTER_ENUM_LOCAL,NULL,5,lpBuffer,dwBufferSize,&dwBufferNeeded,&dwNumStructs);
OutputDebugStringD3("USBMON: After EnumPrinters \n");
if(dwBufferNeeded>dwBufferSize)
{
dwBufferSize=dwBufferNeeded;
lpBuffer=GlobalReAlloc(lpBuffer,dwBufferSize,0);
if(lpBuffer==NULL)
{
OutputDebugStringD1("USBMON: Unable to re-allocate memory in lGetQueues\n");
return ERROR_NOT_ENOUGH_MEMORY;
}
OutputDebugStringD3("USBMON: Before EnumPrinters2 \n");
bStatus=EnumPrinters(PRINTER_ENUM_LOCAL,NULL,5,lpBuffer,dwBufferSize,&dwBufferNeeded,&dwNumStructs);
OutputDebugStringD3("USBMON: After EnumPrinters2 \n");
}
if(bStatus==FALSE)
{
OutputDebugStringD1("USBMON: lGetQueues: EnumPrinters failed\n");
return GetLastError();
}
OutputDebugStringD3("USBMON: lGetQueues: Before for loop \n");
pEnumInfo=(PRINTER_INFO_5 *)lpBuffer;
for(dwLoop=0;dwLoop<dwNumStructs;dwLoop++)
{
OutputDebugStringD3("USBMON: lGetQueues: Head of for loop \n");
if(pEnumInfo->pPortName!=NULL)
{
OutputDebugStringD2("USBMON: lGetQueues: Valid port name \n");
// if(wcsncmp(pEnumInfo->pPortName,PORT_NAME_BASE,wcslen(PORT_NAME_BASE))==0)
if(bCheckPortName(pEnumInfo->pPortName,pBaseNames))
{
OutputDebugStringD3("USBMON: lGetQueues: Valid port name, that starts with registered base name, add it to list \n");
lStatus=lAddQueueToList(pEnumInfo->pPortName,pEnumInfo->pPrinterName,ppQueueList);
if(lStatus!=ERROR_SUCCESS)
{
GlobalFree(lpBuffer);
return lStatus;
}
} /*end if found a USB print queue*/
} /*end if pPortName not NULL*/
pEnumInfo++;
} /*end for loop*/
GlobalFree(lpBuffer);
return ERROR_SUCCESS;
} /*end function lGetQueues*/
BOOL bCheckPortName(LPTSTR pPortName,PUSBMON_BASENAME pBaseNames)
{
BOOL bFound=FALSE;
PUSBMON_BASENAME pWalk;
OutputDebugStringD3("USBMON: Head of bCheckPortName\n");
pWalk=pBaseNames;
while((pWalk!=NULL)&&(!bFound))
{
wsprintf((WCHAR *)szDebugBuff,L"USBMON: PortBaseName==%s\n",pWalk->wcBaseName);
OutputDebugStringWD3((WCHAR *)szDebugBuff);
if(wcsncmp(pPortName,pWalk->wcBaseName,wcslen(pWalk->wcBaseName))==0)
{
bFound=TRUE;
}
else
{
pWalk=pWalk->pNext;
}
} /*end while not found*/
return bFound;
} /*end function bCheckPortName*/
LONG lAddQueueToList(LPWSTR pPortName,LPWSTR pPrinterName,PUSBMON_QUEUE_INFO *ppQueueHead)
{
PUSBMON_QUEUE_INFO pNew,pWalk;
BOOL bFound;
wsprintfW((WCHAR *)szDebugBuff,L"USBMON: Head of lAddQueueToList, about to add queue with port %s\n",pPortName);
OutputDebugStringWD3((WCHAR *)szDebugBuff);
pNew=(PUSBMON_QUEUE_INFO)GlobalAlloc(0,sizeof(USBMON_QUEUE_INFO));
if(pNew==NULL)
{
OutputDebugStringD1("USBMON: vAddQueueToList, Out of memory\n");
return ERROR_NOT_ENOUGH_MEMORY;
}
wcscpy(pNew->wcPortName,pPortName);
if(pPrinterName!=NULL)
wcscpy(pNew->wcPrinterName,pPrinterName);
else
pNew->wcPrinterName[0]=L'\0';
if(*ppQueueHead==NULL)
{
*ppQueueHead=pNew;
pNew->pNext=NULL;
}
else if(lstrcmp(pNew->wcPortName,(*ppQueueHead)->wcPortName)<0)
{
pNew->pNext=*ppQueueHead;
*ppQueueHead=pNew;
}
else
{
pWalk=*ppQueueHead;
bFound=FALSE;
while((!bFound)&&(pWalk->pNext!=NULL))
{
if(lstrcmp(pNew->wcPortName,pWalk->pNext->wcPortName)<0)
bFound=TRUE;
else
pWalk=pWalk->pNext;
}
pNew->pNext=pWalk->pNext;
pWalk->pNext=pNew;
} /*end else, we need to walk the list*/
return ERROR_SUCCESS;
} /*end function vAddQueueToList*/
void vDestroyQueueList(PUSBMON_QUEUE_INFO pQueueList)
{
PUSBMON_QUEUE_INFO pWalk,pLast;
pWalk=pQueueList;
while(pWalk!=NULL)
{
pLast=pWalk;
pWalk=pWalk->pNext;
GlobalFree(pLast);
} /*end while pWalk!=NULL*/
} /*end function vDestroyQueueList*/
LONG BuildReturnTable(int iNumberOfPorts, // Internal variable,
PUSBMON_PORT_INFO pPortList,// List of ports
DWORD Level, // IN specifies structure type to return
LPBYTE Ports, // OUT Buffer to write to
DWORD cBuf, // IN size of buffer provided
LPDWORD pcbNeeded, // OUT specifies bytes written to buffer, or the size the buffer should have been if it's to small
LPDWORD pcReturned) // OUT specifies the number of structures (ports) stored in the buffer
{
PORT_INFO_1 *pInfo1;
PORT_INFO_2 *pInfo2;
VOID *pNextStruct;
WCHAR *pszNextString;
int iNodeSize;
LONG lResult;
unsigned int iStringsSize;
unsigned int iStaticSize; //size of "overhead" strings that are only created once for all ports
unsigned int iAllStructsSize;
unsigned int iAllStringsSize;
unsigned int iTotalSize;
PUSBMON_PORT_INFO pPortWalk;
OutputDebugStringD2("USBMON: Head of BuildReturnTable\n");
wsprintfA(szDebugBuff,"USBMON: iNumberOfPorts==%d, iLevel=%d\n",iNumberOfPorts,Level);
OutputDebugStringD3(szDebugBuff);
if(Level==1)
{
iNodeSize=sizeof(PORT_INFO_1);
iStringsSize=MAX_PORT_LEN*2;
iStaticSize=0;
}
else if(Level==2)
{
iNodeSize=sizeof(PORT_INFO_2);
iStaticSize=(wcslen(MONITOR_NAME)+1)*2;
iStringsSize=(MAX_PORT_LEN*2)+(MAX_PORT_DESC_LEN*2)+iStaticSize;
}
else
{
OutputDebugStringD1("USBMON: Unsupported structure level in BuildReturnTable\n");
lResult=ERROR_INVALID_LEVEL;
goto BuildTableError;
} /*end else it's a level we don't support*/
iAllStructsSize=iNodeSize*iNumberOfPorts;
iAllStringsSize=iStringsSize*iNumberOfPorts;
iTotalSize=iAllStructsSize+iAllStringsSize;
wsprintfA(szDebugBuff,"USBMON: spooler gave us a %lu byte buffer at %X, we need a %lu byte buffer\n",cBuf,Ports,iTotalSize);
OutputDebugStringD3(szDebugBuff);
*pcbNeeded=iTotalSize;
if(iTotalSize>cBuf)
{
OutputDebugStringD3("USBMON: Buffer provided by spooler is not large enough\n");
lResult=ERROR_INSUFFICIENT_BUFFER;
goto BuildTableError;
}
pNextStruct=(VOID *)Ports;
pszNextString=(WCHAR *)(Ports+cBuf-iAllStringsSize); //ports+cbuff == end of the buffer, - iAllStringsSize == start of the strings
// if(Level==2)
// {
// pszMonitorName=(WCHAR *)pszNextString;
// wcscpy(pszMonitorName,MONITOR_NAME);
// pszNextString+=(iStaticSize);
// }
pPortWalk=pPortList;
if(iNumberOfPorts>0)
while(pPortWalk!=NULL)
{
if(Level==1)
{
pInfo1=(PORT_INFO_1 *)pNextStruct;
pInfo1->pName=pszNextString; //crashing line
wcscpy((WCHAR *)(pInfo1->pName),pPortWalk->szPortName);
pszNextString+=(MAX_PORT_LEN);
} /*end if level == 1*/
else
{
OutputDebugStringD2("USBMON: Head of build PORT_INFO 2\n"); //yy
pInfo2=(PORT_INFO_2 *)pNextStruct;
pInfo2->pPortName=pszNextString;
wcscpy((WCHAR *)(pInfo2->pPortName),pPortWalk->szPortName);
pszNextString+=(MAX_PORT_LEN);
pInfo2->pDescription=pszNextString;
wcscpy((WCHAR *)(pInfo2->pDescription),pPortWalk->szPortDescription);
pszNextString+=MAX_PORT_DESC_LEN;
pInfo2->pMonitorName=pszNextString;
wcscpy((WCHAR *)(pInfo2->pMonitorName),MONITOR_NAME);
pszNextString+=(iStaticSize/2); //iStaticSize is bytes, pszNextString in WCHARs
pInfo2->Reserved=0;
pInfo2->fPortType=PORT_TYPE_WRITE;
wsprintfW((WCHAR *)szDebugBuff,L"pInfo2=0x%x\n",pInfo2);
OutputDebugStringWD3((WCHAR *)szDebugBuff);
wsprintfW((WCHAR *)szDebugBuff,L"USBMON in BuildBuff, PortName=%s|\n, Description=%s|\n, MonitorName=%s|\n",pInfo2->pPortName,pInfo2->pDescription,pInfo2->pMonitorName);
OutputDebugStringWD3((WCHAR *)szDebugBuff);
wsprintfW((WCHAR *)szDebugBuff,L"USBMON in BuildBuff, PortName=0x%x\n, Description=0x%x\n, MonitorName=0x%x\n",pInfo2->pPortName,pInfo2->pDescription,pInfo2->pMonitorName);
OutputDebugStringWD3((WCHAR *)szDebugBuff); //yy
} /*else level == 2*/
((PBYTE)pNextStruct)+=iNodeSize;
pPortWalk=pPortWalk->pNext;
} /*end while iLoop*/
*pcReturned=iNumberOfPorts;
return ERROR_SUCCESS;
BuildTableError:
return lResult;
} /*end function BuildReturnTable*/
void FreePrinterList(PUSBMON_PRINTER_INFO pPrinterList)
{
PUSBMON_PRINTER_INFO pWalk,pNext;
pWalk=pPrinterList;
while(pWalk!=NULL)
{
pNext=pWalk->pNext;
GlobalFree(pWalk);
pWalk=pNext;
}
} /*end function vFreePrinterList*/
int iCountPresentPrinters(PUSBMON_PORT_INFO pHead)
{
int iReturn=0;
PUSBMON_PORT_INFO pWalk;
pWalk=pHead;
OutputDebugStringD3("USBMON: ************************************* Head of iCountPresentPrinters\n");
while(pWalk!=NULL)
{
if((pWalk->dwDeviceFlags)&SPINT_ACTIVE)
iReturn++;
pWalk=pWalk->pNext;
}
return iReturn;
} /*end function iCountPrinters*/
/*******************************************************
* FUNCTION: pGetPrintersAndPorts
* Uses SetupDi calls to obtain list of USB printers
* present in the system, and reads the port name
* of the printer from the registry. This function
* replaces pGetPrinterList, UpdateAssociations,
* AllocateNewPorts, DoBestEffortMatches, and
* ReattachExactMatches
*
* This function is called initially with a null pointer
* And is then called again on each EnumPorts
* PARAMETERS:
* PUSBMON_PORT_INFO *ppHead
* Pointer to the head pointer of the list to by modified
* or Created
* RETURN:
* status code
********************************************************/
LONG lGetPrintersAndPorts(PUSBMON_PORT_INFO *ppHead,PUSBMON_BASENAME *ppBaseNames)
{
int iLoop;
LONG lStatus;
HDEVINFO hDeviceList;
SP_DEVICE_INTERFACE_DATA rDeviceInfo;
PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceDetail;
GUID *pPrinterGuid;
BOOL bMoreDevices;
DWORD dwRequiredSize;
PUSBMON_PRINTER_INFO pPrinterList=NULL,pNew;
HKEY hDeviceKey;
DWORD dwError = ERROR_SUCCESS;
OutputDebugStringD2("USBMON: Head of pGetPrinterAndPortList\n");
pPrinterGuid=(GUID *)&USB_PRINTER_GUID;
OutputDebugStringD3("USBMON: before SetupDiGetClassDevs\n");
hDeviceList=SetupDiGetClassDevs(pPrinterGuid,NULL,NULL,DIGCF_INTERFACEDEVICE);
OutputDebugStringD3("USBMON: after SetupDiGetClassDevs\n");
if(hDeviceList==INVALID_HANDLE_VALUE)
{
dwError = GetLastError();
OutputDebugStringD1("USBMON: SetupDiGetClassDevs failed\n");
goto SetupDiPrinterAndPortError;
}
else
{
iLoop=0;
rDeviceInfo.cbSize=sizeof(rDeviceInfo);
bMoreDevices=SetupDiEnumDeviceInterfaces(hDeviceList,0,pPrinterGuid,iLoop,&rDeviceInfo);
wsprintfA(szDebugBuff,"USBMON: SetupDiEnumDeviceInterfaces, data.flags=%u\n",rDeviceInfo.Flags);
OutputDebugStringD3(szDebugBuff);
while(bMoreDevices)
{
if(!SetupDiGetDeviceInterfaceDetail(hDeviceList,&rDeviceInfo,NULL,0,&dwRequiredSize,NULL))
{
dwError=GetLastError();
wsprintfA(szDebugBuff,"USBMON: SetupDiGetDeviceInterfaceDetail first call failed, error=%x\n",dwError);
OutputDebugStringD3(szDebugBuff);
// goto SetupDiPrinterAndPortError; //the first call is just to get this size, so of course it should fail. Don't goto anywhere
}
pDeviceDetail=(PSP_DEVICE_INTERFACE_DETAIL_DATA)GlobalAlloc(0,dwRequiredSize);
if(pDeviceDetail==NULL)
{
OutputDebugStringD1("USBMON: Unable to allocate memory in pGetPrinterList\n");
SetupDiDestroyDeviceInfoList(hDeviceList);
dwError = ERROR_NOT_ENOUGH_MEMORY;
goto SetupDiPrinterAndPortError;
}
pDeviceDetail->cbSize=sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if(!SetupDiGetDeviceInterfaceDetail(hDeviceList,&rDeviceInfo,pDeviceDetail,dwRequiredSize,&dwRequiredSize,NULL))
{
dwError = GetLastError();
OutputDebugStringD1("USBMON: SetupDiGetDeviceInterfaceDetail (second call) failed\n");
SetupDiDestroyDeviceInfoList(hDeviceList);
goto SetupDiPrinterAndPortError;
}
else
OutputDebugStringD3("USBMON: SetupDiGetDeviceInterfaceDetail (second call) OK\n");
lStatus=lAddPrinterToList(ppHead,hDeviceList,&rDeviceInfo,pDeviceDetail,ppBaseNames);
GlobalFree(pDeviceDetail);
OutputDebugStringD3("USBMON: Before end of loop SetupDiEnumDeviceInterfaces\n"); //yy
bMoreDevices=SetupDiEnumDeviceInterfaces(hDeviceList,0,pPrinterGuid,++iLoop,&rDeviceInfo);
wsprintfA(szDebugBuff,"USBMON: SetupDiEnumDeviceInterfaces, data.flags=%u\n",rDeviceInfo.Flags);
OutputDebugStringD3(szDebugBuff);
} /*end while more devices*/
SetupDiDestroyDeviceInfoList(hDeviceList);
return STATUS_SUCCESS;
} /*end else*/
SetupDiPrinterAndPortError:;
if ( dwError == ERROR_SUCCESS )
dwError = ERROR_INVALID_DATA;
OutputDebugStringD1("USBMON: Erroring out of pGetPrinterList\n");
return dwError;
} /*end function lGetPrintersAndPorts*/
long lAddPrinterToList(PUSBMON_PORT_INFO *ppHead,HDEVINFO hDeviceList,SP_DEVICE_INTERFACE_DATA * prDeviceInfo,PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceDetail,PUSBMON_BASENAME *ppBaseNames)
{
PUSBMON_PORT_INFO pWalk,pTemp,pNew = NULL;
BOOL bFound=FALSE;
HANDLE hDeviceKey = INVALID_HANDLE_VALUE;
DWORD dwPortNumberSize;
WCHAR wcPortName[MAX_PORT_LEN+1];
WCHAR wcPortBaseName[MAX_PORT_LEN]; //arbitrary size, bigger than it needs to be
DWORD dwPortNumber,dwStringSize;
DWORD dwReturn = ERROR_SUCCESS;
int iResult;
pWalk=*ppHead;
while((pWalk!=NULL)&&(!bFound))
{
if(lstrcmp(pWalk->DevicePath,pDeviceDetail->DevicePath)==0)
bFound=TRUE;
else
pWalk=pWalk->pNext;
}
if(pWalk!=NULL) //it's not a new node
{
if((!((pWalk->dwDeviceFlags)&SPINT_ACTIVE)) && ((prDeviceInfo->Flags)&SPINT_ACTIVE)) //If we just became active
{
hDeviceKey=SetupDiOpenDeviceInterfaceRegKey(hDeviceList,prDeviceInfo,0,KEY_ALL_ACCESS);
if(hDeviceKey==INVALID_HANDLE_VALUE)
{
OutputDebugStringD1("USBMON: reactivation: SetupDiOpenDeviceInterfaceRegKey failed\n");
return ERROR_ACCESS_DENIED;
}
RegDeleteValue(hDeviceKey,L"recyclable");
dwStringSize = sizeof(pWalk->szPortDescription);
if(RegQueryValueEx(hDeviceKey,L"Port Description",0,NULL,(LPBYTE)(pWalk->szPortDescription),&dwStringSize)!=ERROR_SUCCESS)
{
OutputDebugStringD2("USBMON: RegQueryValueEx, get \"Port Description\" in lAddPrinterToList (refresh) failed, defaulting to \"Virtual printer port for USB\"\n");
wcscpy(pWalk->szPortDescription,L"Virtual printer port for USB");
}
RegCloseKey(hDeviceKey);
hDeviceKey=INVALID_HANDLE_VALUE;
} /*end if re-activated port*/
pWalk->dwDeviceFlags=prDeviceInfo->Flags; //even if we don't need to reload the whole device detail, we need to recheck the flags
}
else
{
pNew=GlobalAlloc(0,sizeof(USBMON_PORT_INFO));
if(pNew==NULL)
return ERROR_NOT_ENOUGH_MEMORY;
wcscpy(pNew->DevicePath,pDeviceDetail->DevicePath);
pNew->iRefCount=0;
hDeviceKey=SetupDiOpenDeviceInterfaceRegKey(hDeviceList,prDeviceInfo,0,KEY_ALL_ACCESS);
if(hDeviceKey==INVALID_HANDLE_VALUE)
{
dwReturn = GetLastError();
OutputDebugStringD1("USBMON: SetupDiOpenDeviceInterfaceRegKey failed\n");
goto Done;
}
dwPortNumberSize=sizeof(dwPortNumber);
dwReturn = RegQueryValueEx(hDeviceKey,L"Port Number",0,NULL,(LPBYTE)&dwPortNumber, &dwPortNumberSize);
if ( dwReturn != ERROR_SUCCESS )
{
OutputDebugStringD2("USBMON: RegQueryValueEx get \"Port Number\" in lAddPrinterToList failed\n");
goto Done;
}
dwStringSize=sizeof(wcPortBaseName);
if(RegQueryValueEx(hDeviceKey,L"Base Name",0,NULL,(LPBYTE)wcPortBaseName,&dwStringSize)!=ERROR_SUCCESS)
{
OutputDebugStringD2("USBMON: RegQueryValueEx, get \"Base Name\" in lAddPrinterToList failed, defaulting to USB\n");
wcscpy(wcPortBaseName,L"USB");
}
vAddNameToBaseNameList(ppBaseNames,wcPortBaseName);
dwStringSize=sizeof(pNew->szPortDescription);
dwReturn=RegQueryValueEx(hDeviceKey,L"Port Description",0,NULL,(LPBYTE)(pNew->szPortDescription),&dwStringSize);
if(dwReturn!=ERROR_SUCCESS)
{
wsprintfA(szDebugBuff,"USBMON: RegQueryValueEx returned (signed) %d, (unsigned) %u\n",dwReturn,dwReturn);
OutputDebugStringD2(szDebugBuff);
OutputDebugStringD2("USBMON: *************************************************RegQueryValueEx, get \"Port Description\" in lAddPrinterToList failed, defaulting to \"Virtual printer port for USB\"\n");
wcscpy(pNew->szPortDescription,L"Virtual printer port for USB");
}
else
{
OutputDebugStringD2("USBMON: *****************************************RegQueryValueEx on baseName OK\n");
}
wsprintf(wcPortName,L"%s%03u",wcPortBaseName,dwPortNumber);
OutputDebugStringD3("USBMON: computed port name ==");
OutputDebugStringWD3(wcPortName);
wcscpy(pNew->szPortName,wcPortName);
pNew->dwDeviceFlags=prDeviceInfo->Flags;
if((pNew->dwDeviceFlags)&SPINT_ACTIVE)
RegDeleteValue(hDeviceKey,L"recyclable");
OutputDebugStringD3("USBMON: AddPrinterToList Start of insertion\n");
pWalk=*ppHead;
if(pWalk==NULL)
{
*ppHead=pNew;
pNew->pNext=NULL;
pNew = NULL;
}
else if(lstrcmp(pNew->szPortName,pWalk->szPortName)<0)
{
OutputDebugStringD3("USBMON: AddPrinterToList New Head\n");
pNew->pNext=*ppHead;
(*ppHead)=pNew;
pNew = NULL;
}
else if(lstrcmp(pNew->szPortName,pWalk->szPortName)==0)
{
pNew->pNext=(*ppHead)->pNext;
(*ppHead)=pNew;
GlobalFree(pWalk);
pNew = NULL;
}
else
{
if(pWalk->pNext!=NULL)
{
iResult=lstrcmp(pNew->szPortName,pWalk->pNext->szPortName);
}
while((iResult>0)&&(pWalk->pNext!=NULL))
{
pWalk=pWalk->pNext;
if(pWalk->pNext!=NULL)
{
iResult=lstrcmp(pNew->szPortName,pWalk->pNext->szPortName);
}
} /*end while*/
if(pWalk->pNext!=NULL)
if(iResult==0) //they match
{
pTemp=pWalk->pNext;
pWalk->pNext=pWalk->pNext->pNext;
GlobalFree(pTemp);
}
pNew->pNext=pWalk->pNext;
pWalk->pNext=pNew;
pNew = NULL;
} /*end else*/
} /*end else pWalk==NULL, therefore it's a new node*/
dwReturn = ERROR_SUCCESS;
Done:
if ( pNew )
GlobalFree(pNew);
if ( hDeviceKey != INVALID_HANDLE_VALUE )
RegCloseKey(hDeviceKey);
return dwReturn;
} /*end function lAddPrinterToList*/
void vAddNameToBaseNameList(PUSBMON_BASENAME *ppBaseNames,WCHAR *wcPortBaseName)
{
BOOL bFound;
PUSBMON_BASENAME pWalk,pNew;
pWalk=*ppBaseNames;
bFound=FALSE;
while((pWalk!=NULL)&&(!bFound))
{
if(wcscmp(pWalk->wcBaseName,wcPortBaseName)==0)
bFound=TRUE;
pWalk=pWalk->pNext;
} /*end while more items*/
if(!bFound)
{
pWalk=*ppBaseNames;
pNew=GlobalAlloc(0,sizeof(USBMON_BASENAME));
if(pNew==NULL)
return;
wcscpy(pNew->wcBaseName,wcPortBaseName);
if(*ppBaseNames==NULL)
{
*ppBaseNames=pNew;
pNew->pNext=NULL;
}
else if(wcscmp(pNew->wcBaseName,pWalk->wcBaseName)<0)
{
pNew->pNext=*ppBaseNames;
*ppBaseNames=pNew;
}
else
{
while((!bFound)&&(pWalk->pNext!=NULL))
{
if(wcscmp(pNew->wcBaseName,pWalk->pNext->wcBaseName)>0)
bFound=TRUE;
else
pWalk=pWalk->pNext;
}
pNew->pNext=pWalk->pNext;
pWalk->pNext=pNew;
} /*end else we need to insert it (not new head)*/
} /*end if need to add*/
} /*end function vAddNameToBaseNameList*/
char *WtoA(WCHAR *pInString)
{
static char szDest[256];
char *pSourceWalk;
char *pszDestWalk;
pszDestWalk=szDest;
pSourceWalk=(char *)pInString;
while(*pSourceWalk!='\0')
{
*(pszDestWalk++)=*pSourceWalk;
pSourceWalk+=2;
}
(*pszDestWalk)='\0';
wsprintfA(szDebugBuff,"USBMON, WtoA, About to return %s\n",szDest);
OutputDebugStringD3(szDebugBuff); //yy
return szDest;
}
void vCleanUpQueuesAndPorts(PUSBMON_PORT_INFO * ppPortInfo,int iNumberOfPorts,PUSBMON_BASENAME pBaseNames)
{
DWORD dwThreadID;
PCLEANUP_THREAD_PARAMS pCleanupParams;
pCleanupParams=(PCLEANUP_THREAD_PARAMS)GlobalAlloc(0,sizeof(CLEANUP_THREAD_PARAMS));
if(pCleanupParams==NULL)
{
OutputDebugStringD1("USBMON: failed to allocate memory in vCleanupQueuesAndPorts\n");
return;
}
pCleanupParams->ppPortInfo=ppPortInfo;
pCleanupParams->iPortCount=iNumberOfPorts;
pCleanupParams->hSemaphore=hMonitorSemaphore;
pCleanupParams->pBaseNames=pBaseNames;
CreateThread(NULL,0,CleanupThread,pCleanupParams,0,&dwThreadID);
}
DWORD WINAPI CleanupThread(LPVOID pParam)
{
PCLEANUP_THREAD_PARAMS pParams;
PUSBMON_QUEUE_INFO pQueueList;
DWORD dwStatus;
pParams=(PCLEANUP_THREAD_PARAMS)pParam;
pQueueList=NULL;
lGetQueues(&pQueueList,pParams->pBaseNames);
if(pQueueList==NULL)
{
OutputDebugStringD3("USBMON: CleanupThread, pQueueList==NULL\n");
}
else
{
OutputDebugStringD3("USBMON: CleanupThread, pQueueList!=NULL\n");
}
wsprintfA(szDebugBuff,"USBMON:+++++++++++++++++++++++++++++++++++++++ Head of CleanupThread, before WaitForSingleObject, hMonitorSemaphore=%x\n",hMonitorSemaphore);
OutputDebugStringD2(szDebugBuff);
dwStatus=WaitForSingleObject(hMonitorSemaphore,INFINITE);
if(dwStatus==WAIT_FAILED)
OutputDebugStringD1("USBMON: WaitForSingleObject failed!\n");
wsprintfA(szDebugBuff,"USBMON: CleanupThread: WaitForSingleObject returned %d\n",dwStatus);
OutputDebugStringD3(szDebugBuff);
OutputDebugStringD2("USBMON: Head of CleanupThread, after WaitForSingleObject\n");
vEliminateOldQueuesAndPorts(pQueueList,pParams->ppPortInfo);
vDestroyQueueList(pQueueList);
GlobalFree(pParams);
OutputDebugStringD2("USBMON: tail of CleanupThread, about to release semaphore++++++++++++++++++++++++++++++++++++++++++++\n");
iCleanupThreads--;
ReleaseSemaphore(hMonitorSemaphore,1,NULL);
return 0;
}
void vEliminateOldQueuesAndPorts(PUSBMON_QUEUE_INFO pQueueInfo,PUSBMON_PORT_INFO * ppPortHead)
{
PUSBMON_QUEUE_INFO pQueueWalk;
PUSBMON_PORT_INFO pPortWalk;
HDEVINFO hDevInfo;
int iCompare;
BOOL bNull=FALSE;
hDevInfo=SetupDiGetClassDevs((GUID *)&USB_PRINTER_GUID,NULL,NULL,DIGCF_INTERFACEDEVICE);
if ( hDevInfo == INVALID_HANDLE_VALUE )
return;
pQueueWalk=pQueueInfo;
pPortWalk= *ppPortHead;
pPortWalk=*ppPortHead;
if((pPortWalk!=NULL)&&(pQueueWalk!=NULL))
{
iCompare=lstrcmp(pPortWalk->szPortName,pQueueWalk->wcPortName);
wsprintf((WCHAR *)szDebugBuff,L"USBMON: About to compare %s and %s\n",pPortWalk->szPortName,pQueueWalk->wcPortName);
OutputDebugStringWD2((WCHAR *)szDebugBuff);
}
else
bNull=TRUE;
while(!bNull)
{
//Walk through matching items loop
while((iCompare==0)&&(!bNull))
{
wsprintfA(szDebugBuff,"USBMON: in cleanup loop, flags=%d\n",pPortWalk->dwDeviceFlags);
OutputDebugStringD2(szDebugBuff);
if((pPortWalk->dwDeviceFlags)&SPINT_ACTIVE)
vUnGreyQueue(pQueueWalk);
else
vGreyOutQueue(pQueueWalk);
pPortWalk=pPortWalk->pNext;
pQueueWalk=pQueueWalk->pNext;
if((pPortWalk!=NULL)&&(pQueueWalk!=NULL))
{
iCompare=lstrcmp(pPortWalk->szPortName,pQueueWalk->wcPortName);
} /*end if no nulls*/
else
bNull=TRUE;
} /*end while matching items*/
// grey out "detached" printers loop
while((iCompare>0)&&(!bNull))
{
OutputDebugStringD3("USBMON: About to grey out queue inside the \"grey queue\" inner loop\n");
//vGreyOutQueue(pQueueWalk); //perhaps something else should happen here. What does it mean if a port is gone but the queue is still around?
pQueueWalk=pQueueWalk->pNext;
if(pQueueWalk!=NULL)
{
wsprintf((WCHAR *)szDebugBuff,L"USBMON: About to compare %s and %s\n",pPortWalk->szPortName,pQueueWalk->wcPortName);
OutputDebugStringWD2((WCHAR *)szDebugBuff);
iCompare=lstrcmp(pPortWalk->szPortName,pQueueWalk->wcPortName);
}
else
bNull=TRUE;
} /*end grey out loop*/
// delete orphaned port names loop
while((iCompare<0)&&(!bNull))
{
if(!((pPortWalk->dwDeviceFlags)&SPINT_ACTIVE))
vDeletePort(pPortWalk, hDevInfo);
pPortWalk=pPortWalk->pNext;
if(pPortWalk!=NULL)
{
wsprintf((WCHAR *)szDebugBuff,L"USBMON: About to compare %s and %s\n",pPortWalk->szPortName,pQueueWalk->wcPortName);
OutputDebugStringWD2((WCHAR *)szDebugBuff);
iCompare=lstrcmp(pPortWalk->szPortName,pQueueWalk->wcPortName);
}
else
bNull=TRUE;
} /*end delete ports loop*/
} /*end while both lists not null (outer loop)*/
//grey out "detached" printers at end of list loop
while(pQueueWalk!=NULL)
{
OutputDebugStringD2("USBMON: About to grey out queue inside the \"grey queue\" cleanup loop\n");
vGreyOutQueue(pQueueWalk); //perhaps something else should happen here. What does it mean if a port is gone but the queue is still around?
pQueueWalk=pQueueWalk->pNext;
} //end end of list disable queues list
//delete orphaned ports names at end of list loop
while(pPortWalk!=NULL)
{
if(!((pPortWalk->dwDeviceFlags)&SPINT_ACTIVE))
vDeletePort(pPortWalk, hDevInfo);
pPortWalk=pPortWalk->pNext;
} //end end of list delete ports loop
SetupDiDestroyDeviceInfoList(hDevInfo);
} /*end function vEliminateOldQueuesAndPorts*/
void vGreyOutQueue(PUSBMON_QUEUE_INFO pQueue)
{
#define SET_PRINTER_BUFFER_SIZE 1024
HANDLE hPrinterHandle;
PRINTER_DEFAULTS rPrinterDefaults;
BYTE bPrinterInfo[SET_PRINTER_BUFFER_SIZE];
int iSizeNeeded;
PRINTER_INFO_5 *pPrinterInfo;
wsprintfW((WCHAR *)szDebugBuff,L"USBMON: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GreyOut Queue %s attached to %s\n",pQueue->wcPrinterName,pQueue->wcPortName);
OutputDebugStringWD2((WCHAR *)szDebugBuff);
rPrinterDefaults.pDatatype=NULL;
rPrinterDefaults.pDevMode=NULL;
rPrinterDefaults.DesiredAccess=PRINTER_ACCESS_ADMINISTER|STANDARD_RIGHTS_ALL|SPECIFIC_RIGHTS_ALL;
if(!OpenPrinter(pQueue->wcPrinterName,&hPrinterHandle,&rPrinterDefaults))
OutputDebugStringD1("USBMON: Unable to OpenPrinter in vGreyOutQueue\n");
if(!GetPrinter(hPrinterHandle,5,bPrinterInfo,SET_PRINTER_BUFFER_SIZE,&iSizeNeeded))
{
wsprintfA(szDebugBuff,"USBMON: GetPrinter failed, error code==%d\n",GetLastError());
OutputDebugStringD1(szDebugBuff);
}
if(iSizeNeeded>SET_PRINTER_BUFFER_SIZE)
OutputDebugStringD1("USBMON: Buffer size not big enough in vGreyOutQueue\n");
pPrinterInfo=(PRINTER_INFO_5 *)bPrinterInfo;
(pPrinterInfo->Attributes)|=PRINTER_ATTRIBUTE_WORK_OFFLINE;
OutputDebugStringD2("USBMON: about to SetPrinter\n");
if(!SetPrinter(hPrinterHandle,5,bPrinterInfo,0))
{
wsprintfA(szDebugBuff,"USBMON: SetPrinter failed, error code==%d\n",GetLastError());
OutputDebugStringD1(szDebugBuff);
}
ClosePrinter(hPrinterHandle);
} /*end function vGreyOutQueue*/
void vUnGreyQueue(PUSBMON_QUEUE_INFO pQueue)
{
HANDLE hPrinterHandle;
PRINTER_DEFAULTS rPrinterDefaults;
BYTE bPrinterInfo[SET_PRINTER_BUFFER_SIZE];
int iSizeNeeded;
PRINTER_INFO_5 *pPrinterInfo;
wsprintfW((WCHAR *)szDebugBuff,L"USBMON: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UnGrey Queue %s attached to %s\n",pQueue->wcPrinterName,pQueue->wcPortName);
OutputDebugStringWD3((WCHAR *)szDebugBuff);
rPrinterDefaults.pDatatype=NULL;
rPrinterDefaults.pDevMode=NULL;
rPrinterDefaults.DesiredAccess=PRINTER_ACCESS_ADMINISTER|STANDARD_RIGHTS_ALL|SPECIFIC_RIGHTS_ALL;
if(!OpenPrinter(pQueue->wcPrinterName,&hPrinterHandle,&rPrinterDefaults))
OutputDebugStringD1("USBMON: Unable to OpenPrinter in vGreyOutQueue\n");
if(!GetPrinter(hPrinterHandle,5,bPrinterInfo,SET_PRINTER_BUFFER_SIZE,&iSizeNeeded))
{
wsprintfA(szDebugBuff,"USBMON: GetPrinter failed, error code==%d\n",GetLastError());
OutputDebugStringD1(szDebugBuff);
}
if(iSizeNeeded>SET_PRINTER_BUFFER_SIZE)
OutputDebugStringD1("USBMON: Buffer size not big enough in vUnGreyQueue\n");
pPrinterInfo=(PRINTER_INFO_5 *)bPrinterInfo;
(pPrinterInfo->Attributes)&=(~PRINTER_ATTRIBUTE_WORK_OFFLINE);
OutputDebugStringD3("USBMON: about to SetPrinter\n");
if(!SetPrinter(hPrinterHandle,5,bPrinterInfo,0))
{
wsprintfA(szDebugBuff,"USBMON: SetPrinter failed, error code==%d\n",GetLastError());
OutputDebugStringD1(szDebugBuff);
}
ClosePrinter(hPrinterHandle);
} /*end function vUnGreyQueue*/
/*******************************************
* vDletePort -- marks a port struct as *
* Deleted by setting it's device name to *
* Null and deleting the port name value *
* from the registry *
*******************************************/
void vDeletePort(PUSBMON_PORT_INFO pPort, HDEVINFO hDeviceList)
{
HANDLE hDeviceKey;
// DebugBreak();
wsprintfW((WCHAR *)szDebugBuff,L"USBMON: /********************Head of vDeletePort for %s.\n",pPort->szPortName);
OutputDebugStringWD2((WCHAR *)szDebugBuff);
hDeviceKey=hGetPortRegKey(pPort, hDeviceList);
if(hDeviceKey!=INVALID_HANDLE_VALUE)
{
wsprintfW((WCHAR *)szDebugBuff,L"USBMON: Opened key for port %s.\n",pPort->szPortName);
OutputDebugStringWD3((WCHAR *)szDebugBuff);
// if(RegDeleteValue(hDeviceKey,L"Port Number")==ERROR_SUCCESS)
if(RegSetValueEx(hDeviceKey,L"recyclable",0,REG_NONE,0,0)==ERROR_SUCCESS)
{
OutputDebugStringD3("USBMON: RegSetValue Success\n");
}
else
{
OutputDebugStringD2("USBMON: RegSetValue Failure\n");
}
RegCloseKey(hDeviceKey);
} /*end if hGetProtRegKey worked*/
else
{
wsprintfW((WCHAR *)szDebugBuff,L"USBMON: Unable to locate and delete reg key for %s\n",pPort->szPortName);
OutputDebugStringWD1((WCHAR *)szDebugBuff);
}
} /*end function vDeletePort*/
BOOL
MatchingRegKey(
HKEY hKey,
PUSBMON_PORT_INFO pPort
)
{
WCHAR wcBaseName[MAX_PORT_LEN];
WCHAR wcPortName[MAX_PORT_LEN];
DWORD dwPortNumber;
DWORD dwReadSize;
dwReadSize=sizeof(DWORD);
if(RegQueryValueEx(hKey,L"Port Number",0,NULL,(LPBYTE)&dwPortNumber,&dwReadSize)==ERROR_SUCCESS)
{
dwReadSize=sizeof(wcBaseName);
if(RegQueryValueEx(hKey,L"Base Name",0,NULL,(LPBYTE)wcBaseName,&dwReadSize)!=ERROR_SUCCESS)
{
OutputDebugStringD2("USBMON: Unable to locate basename. Defaulting to \"USB\"\n"); //yy
wcscpy(wcBaseName,L"USB");
}
wsprintf(wcPortName,L"%s%03u",wcBaseName,dwPortNumber);
return wcscmp(wcPortName,pPort->szPortName)==0;
}
return 0;
}
HANDLE hGetPortRegKey(PUSBMON_PORT_INFO pPort, HDEVINFO hDeviceList)
{
GUID *pPrinterGuid;
int iLoop=0;
SP_DEVICE_INTERFACE_DATA rDeviceInfo;
BOOL bMoreDevices,bFound=FALSE;
DWORD dwRequiredSize;
HANDLE hRegHandle;
PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceDetail;
WCHAR wcBaseName[MAX_PORT_LEN];
rDeviceInfo.cbSize=sizeof(rDeviceInfo);
if ( !SetupDiOpenDeviceInterface(hDeviceList, pPort->DevicePath,
DIODI_NO_ADD, &rDeviceInfo) )
return INVALID_HANDLE_VALUE;
hRegHandle = SetupDiOpenDeviceInterfaceRegKey(hDeviceList,
&rDeviceInfo,
0,
KEY_ALL_ACCESS);
if ( hRegHandle != INVALID_HANDLE_VALUE ) {
if ( MatchingRegKey(hRegHandle, pPort) )
return hRegHandle;
CloseHandle(hRegHandle);
}
pPrinterGuid=(GUID *)&USB_PRINTER_GUID;
bMoreDevices=SetupDiEnumDeviceInterfaces(hDeviceList,0,pPrinterGuid,iLoop,&rDeviceInfo);
while((bMoreDevices)&&(!bFound))
{
SetupDiGetDeviceInterfaceDetail(hDeviceList,&rDeviceInfo,NULL,0,&dwRequiredSize,NULL);
pDeviceDetail=(PSP_DEVICE_INTERFACE_DETAIL_DATA)GlobalAlloc(0,dwRequiredSize);
if(pDeviceDetail==NULL)
{
OutputDebugStringD1("USBMON: Unable to allocate memory in pGetPrinterList\n");
return INVALID_HANDLE_VALUE;
}
pDeviceDetail->cbSize=sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if(!SetupDiGetDeviceInterfaceDetail(hDeviceList,&rDeviceInfo,pDeviceDetail,dwRequiredSize,&dwRequiredSize,NULL))
{
OutputDebugStringD1("USBMON: SetupDiGetDeviceInterfaceDetail (second call) failed\n");
return INVALID_HANDLE_VALUE;
} /*end if SetupDiGetDeviceInterfaceDetail, call2 failed*/
hRegHandle=SetupDiOpenDeviceInterfaceRegKey(hDeviceList,&rDeviceInfo,0,KEY_ALL_ACCESS);
if(hRegHandle!=INVALID_HANDLE_VALUE)
{
if ( MatchingRegKey(hRegHandle, pPort) )
bFound=TRUE;
else
CloseHandle(hRegHandle);
} /*end if SetupDiOpenDeviceInterfaceRegKey successful*/
GlobalFree(pDeviceDetail);
bMoreDevices=SetupDiEnumDeviceInterfaces(hDeviceList,0,pPrinterGuid,++iLoop,&rDeviceInfo);
} /*end while more devices & !found*/
if(!bFound)
hRegHandle=INVALID_HANDLE_VALUE;
return hRegHandle;
} /*end function hGetPortRegKey*/