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

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #include <windows.h>
  5. #include <winspool.h>
  6. //#include <wchar.h>
  7. #include <setupapi.h>
  8. //#include <stdlib.h>
  9. #include "enumports.h"
  10. #include "usbmon.h"
  11. void vOldAddItemToPortList(PUSBMON_PORT_INFO *pHead,PUSBMON_PORT_INFO pNew);
  12. PUSBMON_PRINTER_INFO pOldGetPrinterList();
  13. LONG UpdateAssociations(PUSBMON_PORT_INFO *ppPortList,PUSBMON_PRINTER_INFO pPrinterList);
  14. LONG AllocateNewPorts(PUSBMON_PORT_INFO *ppPortList,PUSBMON_PRINTER_INFO pPrinterList);
  15. LONG DoBestEffortMatches(PUSBMON_PORT_INFO pPortList,PUSBMON_PRINTER_INFO pPrinterList);
  16. LONG ReattachExactMatches(PUSBMON_PORT_INFO pPortList,PUSBMON_PRINTER_INFO pPrinterList);
  17. //void InitPortBits(PUSBMON_PORT_INFO pPortList);
  18. //PUSBMON_PORT_INFO pGetNewPortNode(PUSBMON_PORT_INFO *ppListHead);
  19. LONG WriteNewAssociations(int *iNumberOfPorts,PUSBMON_PORT_INFO pPortList,HKEY hPortRoot);
  20. void FreePrinterList(PUSBMON_PRINTER_INFO pPrinterList);
  21. LONG BuildReturnTable(int iNumberOfPorts,PUSBMON_PORT_INFO pPortList,DWORD Level,LPBYTE Ports,DWORD cBuf,LPDWORD pcbNeeded,LPDWORD pcReturned);
  22. char szDebugBuff[512];
  23. char *WtoA(WCHAR *pInString);
  24. long lAddPrinterToList(PUSBMON_PORT_INFO *ppHead,HDEVINFO hDeviceList,PSP_DEVICE_INTERFACE_DATA prDeviceInfo,PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceDetail,PUSBMON_BASENAME *ppBaseNames);
  25. int iCountPresentPrinters(PUSBMON_PORT_INFO pHead);
  26. LONG lGetPrintersAndPorts(PUSBMON_PORT_INFO *ppHead,PUSBMON_BASENAME *);
  27. LONG lGetQueues(PUSBMON_QUEUE_INFO *ppQueueList,PUSBMON_BASENAME pBaseNames);
  28. LONG lAddQueueToList(LPWSTR pPortName,LPWSTR pPrinterName,PUSBMON_QUEUE_INFO *ppQueueHead);
  29. void vDestroyQueueList(PUSBMON_QUEUE_INFO pQueueList);
  30. void vCleanUpQueuesAndPorts(PUSBMON_PORT_INFO * pPortInfo,int iNumberOfPorts,PUSBMON_BASENAME pBaseNames);
  31. DWORD WINAPI CleanupThread(LPVOID pParam);
  32. void vEliminateOldQueuesAndPorts(PUSBMON_QUEUE_INFO pQueueInfo,PUSBMON_PORT_INFO * fpPortInfo);
  33. void vDeletePort(PUSBMON_PORT_INFO pPort, HDEVINFO hDeviceList);
  34. void vGreyOutQueue(PUSBMON_QUEUE_INFO pQueue);
  35. void vUnGreyQueue(PUSBMON_QUEUE_INFO pQueue);
  36. HANDLE hGetPortRegKey(PUSBMON_PORT_INFO pPort, HDEVINFO hDeviceList);
  37. void vAddNameToBaseNameList(PUSBMON_BASENAME *ppBaseNames,WCHAR *wcPortBaseName);
  38. BOOL bCheckPortName(LPTSTR pPortName,PUSBMON_BASENAME pBaseNames);
  39. int iGetNumberOfPorts(PUSBMON_PORT_INFO pHead);
  40. int iCleanupThreads=0;
  41. HKEY hPortsKeyG; //global
  42. PUSBMON_PORT_INFO pPortInfoG=NULL;
  43. int iLastPrintersHere=-1;
  44. typedef struct CLEANUP_THREAD_PARAMS_DEF
  45. {
  46. PUSBMON_PORT_INFO * ppPortInfo;
  47. PUSBMON_BASENAME pBaseNames;
  48. int iPortCount;
  49. HANDLE hSemaphore;
  50. } CLEANUP_THREAD_PARAMS,*PCLEANUP_THREAD_PARAMS;
  51. BOOL WINAPI USBMON_EnumPorts(LPWSTR pName, DWORD Level, LPBYTE pPorts, DWORD cbBuf,LPDWORD pcbNeeded, LPDWORD pcReturned)
  52. {
  53. PUSBMON_PRINTER_INFO pPrinterList;
  54. LONG lResult;
  55. DWORD dwStatus;
  56. int iNumberOfPorts;
  57. static int iOldNumberOfPorts=0;
  58. static int iNumCalls=0;
  59. int iThisCall;
  60. int iPrintersHere;
  61. OutputDebugStringD2("USBMON ++=Head of EnumPorts, before WaitForSingleObject\n");
  62. iThisCall=++iNumCalls;
  63. wsprintfA(szDebugBuff,"USBMON: +++++++++++++++++++++++++++++++++++++++++++++++++EnumPorts call # %d, handle = %x\n",iThisCall,hMonitorSemaphore);
  64. OutputDebugStringD2(szDebugBuff);
  65. dwStatus=WaitForSingleObject(hMonitorSemaphore,INFINITE);
  66. if(dwStatus==WAIT_FAILED)
  67. {
  68. OutputDebugStringD1("USBMON: WaitForSingleObject failed!\n");
  69. }
  70. wsprintfA(szDebugBuff,"USBMON Head of EnumPrts, ++++++++++++++++++++++++++++++++++++ Instance # %d, after WaitForSingleObject, return code=%d\n",iThisCall,dwStatus);
  71. OutputDebugStringD2(szDebugBuff);
  72. lResult=lGetPrintersAndPorts(&pPortInfoG,&GpBaseNameList);
  73. iNumberOfPorts=iGetNumberOfPorts(pPortInfoG);
  74. if(iCleanupThreads==0)
  75. {
  76. iPrintersHere=iCountPresentPrinters(pPortInfoG);
  77. if(iPrintersHere!=iLastPrintersHere)
  78. {
  79. iLastPrintersHere=iPrintersHere;
  80. iCleanupThreads++;
  81. OutputDebugStringD3("USBMON: About to clean up queues and ports\n");
  82. vCleanUpQueuesAndPorts(&pPortInfoG,iNumberOfPorts,GpBaseNameList);
  83. } //end printer count changed
  84. }
  85. lResult=BuildReturnTable(iNumberOfPorts,pPortInfoG,Level,pPorts,cbBuf,pcbNeeded,pcReturned);
  86. if(lResult!=ERROR_SUCCESS)
  87. {
  88. OutputDebugStringD2("USBMON: Unable to build return buffer (this is normal for first call)\n");
  89. goto EnumPortsError;
  90. }
  91. OutputDebugStringD3("USBMON tail of EnumPorts, before ReleaseSemaphore\n");
  92. ReleaseSemaphore(hMonitorSemaphore,1,NULL);
  93. return TRUE;
  94. EnumPortsError:
  95. wsprintfA(szDebugBuff,"USBMON tail of EnumPorts, error path, before ReleaseSemaphore, *pcbNeeded=%d\n",*pcbNeeded);
  96. OutputDebugStringD3(szDebugBuff);
  97. if(!ReleaseSemaphore(hMonitorSemaphore,1,NULL))
  98. {
  99. wsprintfA(szDebugBuff,"USBMON: EnumPorts Release sempahore failed for instance %d \n",iThisCall);
  100. OutputDebugStringD1(szDebugBuff);
  101. }
  102. else
  103. {
  104. wsprintfA(szDebugBuff,"USBMON: EnumPortsRelease sempahore succeeded for instance %d \n",iThisCall);
  105. OutputDebugStringD2(szDebugBuff);
  106. }
  107. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  108. return FALSE;
  109. } /*End EnumPorts*/
  110. int iGetNumberOfPorts(PUSBMON_PORT_INFO pHead)
  111. {
  112. PUSBMON_PORT_INFO pWalk;
  113. int iCount=0;
  114. pWalk=pHead;
  115. while(pWalk!=NULL)
  116. {
  117. iCount++;
  118. pWalk=pWalk->pNext;
  119. }/*end while*/
  120. return iCount;
  121. } /*end function iGetNumberOfPorts*/
  122. /***********************************
  123. * lGetQueues
  124. *
  125. * This function builds a linked list of print queues
  126. * who's port names start with a registered basename.
  127. *
  128. * This list is used to grey out queues who's printers are
  129. * Unavailable, and to delete ports who's printers are gone
  130. ************************************************************/
  131. LONG lGetQueues(PUSBMON_QUEUE_INFO *ppQueueList,PUSBMON_BASENAME pBaseNames)
  132. {
  133. DWORD dwBufferSize=1024;
  134. DWORD dwBufferNeeded=0;
  135. DWORD dwNumStructs;
  136. LPBYTE lpBuffer;
  137. BOOL bStatus;
  138. DWORD dwLoop;
  139. PRINTER_INFO_5 *pEnumInfo;
  140. LONG lStatus;
  141. OutputDebugStringD2("USBMON: Head of lGetQueues \n");
  142. lpBuffer=(LPBYTE)GlobalAlloc(0,dwBufferSize);
  143. if(lpBuffer==NULL)
  144. {
  145. OutputDebugStringD1("USBMON: Unable to allocate memory in lGetQueues\n");
  146. return ERROR_NOT_ENOUGH_MEMORY;
  147. }
  148. OutputDebugStringD3("USBMON: Before EnumPrinters \n");
  149. bStatus=EnumPrinters(PRINTER_ENUM_LOCAL,NULL,5,lpBuffer,dwBufferSize,&dwBufferNeeded,&dwNumStructs);
  150. OutputDebugStringD3("USBMON: After EnumPrinters \n");
  151. if(dwBufferNeeded>dwBufferSize)
  152. {
  153. dwBufferSize=dwBufferNeeded;
  154. lpBuffer=GlobalReAlloc(lpBuffer,dwBufferSize,0);
  155. if(lpBuffer==NULL)
  156. {
  157. OutputDebugStringD1("USBMON: Unable to re-allocate memory in lGetQueues\n");
  158. return ERROR_NOT_ENOUGH_MEMORY;
  159. }
  160. OutputDebugStringD3("USBMON: Before EnumPrinters2 \n");
  161. bStatus=EnumPrinters(PRINTER_ENUM_LOCAL,NULL,5,lpBuffer,dwBufferSize,&dwBufferNeeded,&dwNumStructs);
  162. OutputDebugStringD3("USBMON: After EnumPrinters2 \n");
  163. }
  164. if(bStatus==FALSE)
  165. {
  166. OutputDebugStringD1("USBMON: lGetQueues: EnumPrinters failed\n");
  167. return GetLastError();
  168. }
  169. OutputDebugStringD3("USBMON: lGetQueues: Before for loop \n");
  170. pEnumInfo=(PRINTER_INFO_5 *)lpBuffer;
  171. for(dwLoop=0;dwLoop<dwNumStructs;dwLoop++)
  172. {
  173. OutputDebugStringD3("USBMON: lGetQueues: Head of for loop \n");
  174. if(pEnumInfo->pPortName!=NULL)
  175. {
  176. OutputDebugStringD2("USBMON: lGetQueues: Valid port name \n");
  177. // if(wcsncmp(pEnumInfo->pPortName,PORT_NAME_BASE,wcslen(PORT_NAME_BASE))==0)
  178. if(bCheckPortName(pEnumInfo->pPortName,pBaseNames))
  179. {
  180. OutputDebugStringD3("USBMON: lGetQueues: Valid port name, that starts with registered base name, add it to list \n");
  181. lStatus=lAddQueueToList(pEnumInfo->pPortName,pEnumInfo->pPrinterName,ppQueueList);
  182. if(lStatus!=ERROR_SUCCESS)
  183. {
  184. GlobalFree(lpBuffer);
  185. return lStatus;
  186. }
  187. } /*end if found a USB print queue*/
  188. } /*end if pPortName not NULL*/
  189. pEnumInfo++;
  190. } /*end for loop*/
  191. GlobalFree(lpBuffer);
  192. return ERROR_SUCCESS;
  193. } /*end function lGetQueues*/
  194. BOOL bCheckPortName(LPTSTR pPortName,PUSBMON_BASENAME pBaseNames)
  195. {
  196. BOOL bFound=FALSE;
  197. PUSBMON_BASENAME pWalk;
  198. OutputDebugStringD3("USBMON: Head of bCheckPortName\n");
  199. pWalk=pBaseNames;
  200. while((pWalk!=NULL)&&(!bFound))
  201. {
  202. wsprintf((WCHAR *)szDebugBuff,L"USBMON: PortBaseName==%s\n",pWalk->wcBaseName);
  203. OutputDebugStringWD3((WCHAR *)szDebugBuff);
  204. if(wcsncmp(pPortName,pWalk->wcBaseName,wcslen(pWalk->wcBaseName))==0)
  205. {
  206. bFound=TRUE;
  207. }
  208. else
  209. {
  210. pWalk=pWalk->pNext;
  211. }
  212. } /*end while not found*/
  213. return bFound;
  214. } /*end function bCheckPortName*/
  215. LONG lAddQueueToList(LPWSTR pPortName,LPWSTR pPrinterName,PUSBMON_QUEUE_INFO *ppQueueHead)
  216. {
  217. PUSBMON_QUEUE_INFO pNew,pWalk;
  218. BOOL bFound;
  219. wsprintfW((WCHAR *)szDebugBuff,L"USBMON: Head of lAddQueueToList, about to add queue with port %s\n",pPortName);
  220. OutputDebugStringWD3((WCHAR *)szDebugBuff);
  221. pNew=(PUSBMON_QUEUE_INFO)GlobalAlloc(0,sizeof(USBMON_QUEUE_INFO));
  222. if(pNew==NULL)
  223. {
  224. OutputDebugStringD1("USBMON: vAddQueueToList, Out of memory\n");
  225. return ERROR_NOT_ENOUGH_MEMORY;
  226. }
  227. wcscpy(pNew->wcPortName,pPortName);
  228. if(pPrinterName!=NULL)
  229. wcscpy(pNew->wcPrinterName,pPrinterName);
  230. else
  231. pNew->wcPrinterName[0]=L'\0';
  232. if(*ppQueueHead==NULL)
  233. {
  234. *ppQueueHead=pNew;
  235. pNew->pNext=NULL;
  236. }
  237. else if(lstrcmp(pNew->wcPortName,(*ppQueueHead)->wcPortName)<0)
  238. {
  239. pNew->pNext=*ppQueueHead;
  240. *ppQueueHead=pNew;
  241. }
  242. else
  243. {
  244. pWalk=*ppQueueHead;
  245. bFound=FALSE;
  246. while((!bFound)&&(pWalk->pNext!=NULL))
  247. {
  248. if(lstrcmp(pNew->wcPortName,pWalk->pNext->wcPortName)<0)
  249. bFound=TRUE;
  250. else
  251. pWalk=pWalk->pNext;
  252. }
  253. pNew->pNext=pWalk->pNext;
  254. pWalk->pNext=pNew;
  255. } /*end else, we need to walk the list*/
  256. return ERROR_SUCCESS;
  257. } /*end function vAddQueueToList*/
  258. void vDestroyQueueList(PUSBMON_QUEUE_INFO pQueueList)
  259. {
  260. PUSBMON_QUEUE_INFO pWalk,pLast;
  261. pWalk=pQueueList;
  262. while(pWalk!=NULL)
  263. {
  264. pLast=pWalk;
  265. pWalk=pWalk->pNext;
  266. GlobalFree(pLast);
  267. } /*end while pWalk!=NULL*/
  268. } /*end function vDestroyQueueList*/
  269. LONG BuildReturnTable(int iNumberOfPorts, // Internal variable,
  270. PUSBMON_PORT_INFO pPortList,// List of ports
  271. DWORD Level, // IN specifies structure type to return
  272. LPBYTE Ports, // OUT Buffer to write to
  273. DWORD cBuf, // IN size of buffer provided
  274. LPDWORD pcbNeeded, // OUT specifies bytes written to buffer, or the size the buffer should have been if it's to small
  275. LPDWORD pcReturned) // OUT specifies the number of structures (ports) stored in the buffer
  276. {
  277. PORT_INFO_1 *pInfo1;
  278. PORT_INFO_2 *pInfo2;
  279. VOID *pNextStruct;
  280. WCHAR *pszNextString;
  281. int iNodeSize;
  282. LONG lResult;
  283. unsigned int iStringsSize;
  284. unsigned int iStaticSize; //size of "overhead" strings that are only created once for all ports
  285. unsigned int iAllStructsSize;
  286. unsigned int iAllStringsSize;
  287. unsigned int iTotalSize;
  288. PUSBMON_PORT_INFO pPortWalk;
  289. OutputDebugStringD2("USBMON: Head of BuildReturnTable\n");
  290. wsprintfA(szDebugBuff,"USBMON: iNumberOfPorts==%d, iLevel=%d\n",iNumberOfPorts,Level);
  291. OutputDebugStringD3(szDebugBuff);
  292. if(Level==1)
  293. {
  294. iNodeSize=sizeof(PORT_INFO_1);
  295. iStringsSize=MAX_PORT_LEN*2;
  296. iStaticSize=0;
  297. }
  298. else if(Level==2)
  299. {
  300. iNodeSize=sizeof(PORT_INFO_2);
  301. iStaticSize=(wcslen(MONITOR_NAME)+1)*2;
  302. iStringsSize=(MAX_PORT_LEN*2)+(MAX_PORT_DESC_LEN*2)+iStaticSize;
  303. }
  304. else
  305. {
  306. OutputDebugStringD1("USBMON: Unsupported structure level in BuildReturnTable\n");
  307. lResult=ERROR_INVALID_LEVEL;
  308. goto BuildTableError;
  309. } /*end else it's a level we don't support*/
  310. iAllStructsSize=iNodeSize*iNumberOfPorts;
  311. iAllStringsSize=iStringsSize*iNumberOfPorts;
  312. iTotalSize=iAllStructsSize+iAllStringsSize;
  313. wsprintfA(szDebugBuff,"USBMON: spooler gave us a %lu byte buffer at %X, we need a %lu byte buffer\n",cBuf,Ports,iTotalSize);
  314. OutputDebugStringD3(szDebugBuff);
  315. *pcbNeeded=iTotalSize;
  316. if(iTotalSize>cBuf)
  317. {
  318. OutputDebugStringD3("USBMON: Buffer provided by spooler is not large enough\n");
  319. lResult=ERROR_INSUFFICIENT_BUFFER;
  320. goto BuildTableError;
  321. }
  322. pNextStruct=(VOID *)Ports;
  323. pszNextString=(WCHAR *)(Ports+cBuf-iAllStringsSize); //ports+cbuff == end of the buffer, - iAllStringsSize == start of the strings
  324. // if(Level==2)
  325. // {
  326. // pszMonitorName=(WCHAR *)pszNextString;
  327. // wcscpy(pszMonitorName,MONITOR_NAME);
  328. // pszNextString+=(iStaticSize);
  329. // }
  330. pPortWalk=pPortList;
  331. if(iNumberOfPorts>0)
  332. while(pPortWalk!=NULL)
  333. {
  334. if(Level==1)
  335. {
  336. pInfo1=(PORT_INFO_1 *)pNextStruct;
  337. pInfo1->pName=pszNextString; //crashing line
  338. wcscpy((WCHAR *)(pInfo1->pName),pPortWalk->szPortName);
  339. pszNextString+=(MAX_PORT_LEN);
  340. } /*end if level == 1*/
  341. else
  342. {
  343. OutputDebugStringD2("USBMON: Head of build PORT_INFO 2\n"); //yy
  344. pInfo2=(PORT_INFO_2 *)pNextStruct;
  345. pInfo2->pPortName=pszNextString;
  346. wcscpy((WCHAR *)(pInfo2->pPortName),pPortWalk->szPortName);
  347. pszNextString+=(MAX_PORT_LEN);
  348. pInfo2->pDescription=pszNextString;
  349. wcscpy((WCHAR *)(pInfo2->pDescription),pPortWalk->szPortDescription);
  350. pszNextString+=MAX_PORT_DESC_LEN;
  351. pInfo2->pMonitorName=pszNextString;
  352. wcscpy((WCHAR *)(pInfo2->pMonitorName),MONITOR_NAME);
  353. pszNextString+=(iStaticSize/2); //iStaticSize is bytes, pszNextString in WCHARs
  354. pInfo2->Reserved=0;
  355. pInfo2->fPortType=PORT_TYPE_WRITE;
  356. wsprintfW((WCHAR *)szDebugBuff,L"pInfo2=0x%x\n",pInfo2);
  357. OutputDebugStringWD3((WCHAR *)szDebugBuff);
  358. wsprintfW((WCHAR *)szDebugBuff,L"USBMON in BuildBuff, PortName=%s|\n, Description=%s|\n, MonitorName=%s|\n",pInfo2->pPortName,pInfo2->pDescription,pInfo2->pMonitorName);
  359. OutputDebugStringWD3((WCHAR *)szDebugBuff);
  360. 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);
  361. OutputDebugStringWD3((WCHAR *)szDebugBuff); //yy
  362. } /*else level == 2*/
  363. ((PBYTE)pNextStruct)+=iNodeSize;
  364. pPortWalk=pPortWalk->pNext;
  365. } /*end while iLoop*/
  366. *pcReturned=iNumberOfPorts;
  367. return ERROR_SUCCESS;
  368. BuildTableError:
  369. return lResult;
  370. } /*end function BuildReturnTable*/
  371. void FreePrinterList(PUSBMON_PRINTER_INFO pPrinterList)
  372. {
  373. PUSBMON_PRINTER_INFO pWalk,pNext;
  374. pWalk=pPrinterList;
  375. while(pWalk!=NULL)
  376. {
  377. pNext=pWalk->pNext;
  378. GlobalFree(pWalk);
  379. pWalk=pNext;
  380. }
  381. } /*end function vFreePrinterList*/
  382. int iCountPresentPrinters(PUSBMON_PORT_INFO pHead)
  383. {
  384. int iReturn=0;
  385. PUSBMON_PORT_INFO pWalk;
  386. pWalk=pHead;
  387. OutputDebugStringD3("USBMON: ************************************* Head of iCountPresentPrinters\n");
  388. while(pWalk!=NULL)
  389. {
  390. if((pWalk->dwDeviceFlags)&SPINT_ACTIVE)
  391. iReturn++;
  392. pWalk=pWalk->pNext;
  393. }
  394. return iReturn;
  395. } /*end function iCountPrinters*/
  396. /*******************************************************
  397. * FUNCTION: pGetPrintersAndPorts
  398. * Uses SetupDi calls to obtain list of USB printers
  399. * present in the system, and reads the port name
  400. * of the printer from the registry. This function
  401. * replaces pGetPrinterList, UpdateAssociations,
  402. * AllocateNewPorts, DoBestEffortMatches, and
  403. * ReattachExactMatches
  404. *
  405. * This function is called initially with a null pointer
  406. * And is then called again on each EnumPorts
  407. * PARAMETERS:
  408. * PUSBMON_PORT_INFO *ppHead
  409. * Pointer to the head pointer of the list to by modified
  410. * or Created
  411. * RETURN:
  412. * status code
  413. ********************************************************/
  414. LONG lGetPrintersAndPorts(PUSBMON_PORT_INFO *ppHead,PUSBMON_BASENAME *ppBaseNames)
  415. {
  416. int iLoop;
  417. LONG lStatus;
  418. HDEVINFO hDeviceList;
  419. SP_DEVICE_INTERFACE_DATA rDeviceInfo;
  420. PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceDetail;
  421. GUID *pPrinterGuid;
  422. BOOL bMoreDevices;
  423. DWORD dwRequiredSize;
  424. PUSBMON_PRINTER_INFO pPrinterList=NULL,pNew;
  425. HKEY hDeviceKey;
  426. DWORD dwError = ERROR_SUCCESS;
  427. OutputDebugStringD2("USBMON: Head of pGetPrinterAndPortList\n");
  428. pPrinterGuid=(GUID *)&USB_PRINTER_GUID;
  429. OutputDebugStringD3("USBMON: before SetupDiGetClassDevs\n");
  430. hDeviceList=SetupDiGetClassDevs(pPrinterGuid,NULL,NULL,DIGCF_INTERFACEDEVICE);
  431. OutputDebugStringD3("USBMON: after SetupDiGetClassDevs\n");
  432. if(hDeviceList==INVALID_HANDLE_VALUE)
  433. {
  434. dwError = GetLastError();
  435. OutputDebugStringD1("USBMON: SetupDiGetClassDevs failed\n");
  436. goto SetupDiPrinterAndPortError;
  437. }
  438. else
  439. {
  440. iLoop=0;
  441. rDeviceInfo.cbSize=sizeof(rDeviceInfo);
  442. bMoreDevices=SetupDiEnumDeviceInterfaces(hDeviceList,0,pPrinterGuid,iLoop,&rDeviceInfo);
  443. wsprintfA(szDebugBuff,"USBMON: SetupDiEnumDeviceInterfaces, data.flags=%u\n",rDeviceInfo.Flags);
  444. OutputDebugStringD3(szDebugBuff);
  445. while(bMoreDevices)
  446. {
  447. if(!SetupDiGetDeviceInterfaceDetail(hDeviceList,&rDeviceInfo,NULL,0,&dwRequiredSize,NULL))
  448. {
  449. dwError=GetLastError();
  450. wsprintfA(szDebugBuff,"USBMON: SetupDiGetDeviceInterfaceDetail first call failed, error=%x\n",dwError);
  451. OutputDebugStringD3(szDebugBuff);
  452. // goto SetupDiPrinterAndPortError; //the first call is just to get this size, so of course it should fail. Don't goto anywhere
  453. }
  454. pDeviceDetail=(PSP_DEVICE_INTERFACE_DETAIL_DATA)GlobalAlloc(0,dwRequiredSize);
  455. if(pDeviceDetail==NULL)
  456. {
  457. OutputDebugStringD1("USBMON: Unable to allocate memory in pGetPrinterList\n");
  458. SetupDiDestroyDeviceInfoList(hDeviceList);
  459. dwError = ERROR_NOT_ENOUGH_MEMORY;
  460. goto SetupDiPrinterAndPortError;
  461. }
  462. pDeviceDetail->cbSize=sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  463. if(!SetupDiGetDeviceInterfaceDetail(hDeviceList,&rDeviceInfo,pDeviceDetail,dwRequiredSize,&dwRequiredSize,NULL))
  464. {
  465. dwError = GetLastError();
  466. OutputDebugStringD1("USBMON: SetupDiGetDeviceInterfaceDetail (second call) failed\n");
  467. SetupDiDestroyDeviceInfoList(hDeviceList);
  468. goto SetupDiPrinterAndPortError;
  469. }
  470. else
  471. OutputDebugStringD3("USBMON: SetupDiGetDeviceInterfaceDetail (second call) OK\n");
  472. lStatus=lAddPrinterToList(ppHead,hDeviceList,&rDeviceInfo,pDeviceDetail,ppBaseNames);
  473. GlobalFree(pDeviceDetail);
  474. OutputDebugStringD3("USBMON: Before end of loop SetupDiEnumDeviceInterfaces\n"); //yy
  475. bMoreDevices=SetupDiEnumDeviceInterfaces(hDeviceList,0,pPrinterGuid,++iLoop,&rDeviceInfo);
  476. wsprintfA(szDebugBuff,"USBMON: SetupDiEnumDeviceInterfaces, data.flags=%u\n",rDeviceInfo.Flags);
  477. OutputDebugStringD3(szDebugBuff);
  478. } /*end while more devices*/
  479. SetupDiDestroyDeviceInfoList(hDeviceList);
  480. return STATUS_SUCCESS;
  481. } /*end else*/
  482. SetupDiPrinterAndPortError:;
  483. if ( dwError == ERROR_SUCCESS )
  484. dwError = ERROR_INVALID_DATA;
  485. OutputDebugStringD1("USBMON: Erroring out of pGetPrinterList\n");
  486. return dwError;
  487. } /*end function lGetPrintersAndPorts*/
  488. long lAddPrinterToList(PUSBMON_PORT_INFO *ppHead,HDEVINFO hDeviceList,SP_DEVICE_INTERFACE_DATA * prDeviceInfo,PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceDetail,PUSBMON_BASENAME *ppBaseNames)
  489. {
  490. PUSBMON_PORT_INFO pWalk,pTemp,pNew = NULL;
  491. BOOL bFound=FALSE;
  492. HANDLE hDeviceKey = INVALID_HANDLE_VALUE;
  493. DWORD dwPortNumberSize;
  494. WCHAR wcPortName[MAX_PORT_LEN+1];
  495. WCHAR wcPortBaseName[MAX_PORT_LEN]; //arbitrary size, bigger than it needs to be
  496. DWORD dwPortNumber,dwStringSize;
  497. DWORD dwReturn = ERROR_SUCCESS;
  498. int iResult;
  499. pWalk=*ppHead;
  500. while((pWalk!=NULL)&&(!bFound))
  501. {
  502. if(lstrcmp(pWalk->DevicePath,pDeviceDetail->DevicePath)==0)
  503. bFound=TRUE;
  504. else
  505. pWalk=pWalk->pNext;
  506. }
  507. if(pWalk!=NULL) //it's not a new node
  508. {
  509. if((!((pWalk->dwDeviceFlags)&SPINT_ACTIVE)) && ((prDeviceInfo->Flags)&SPINT_ACTIVE)) //If we just became active
  510. {
  511. hDeviceKey=SetupDiOpenDeviceInterfaceRegKey(hDeviceList,prDeviceInfo,0,KEY_ALL_ACCESS);
  512. if(hDeviceKey==INVALID_HANDLE_VALUE)
  513. {
  514. OutputDebugStringD1("USBMON: reactivation: SetupDiOpenDeviceInterfaceRegKey failed\n");
  515. return ERROR_ACCESS_DENIED;
  516. }
  517. RegDeleteValue(hDeviceKey,L"recyclable");
  518. dwStringSize = sizeof(pWalk->szPortDescription);
  519. if(RegQueryValueEx(hDeviceKey,L"Port Description",0,NULL,(LPBYTE)(pWalk->szPortDescription),&dwStringSize)!=ERROR_SUCCESS)
  520. {
  521. OutputDebugStringD2("USBMON: RegQueryValueEx, get \"Port Description\" in lAddPrinterToList (refresh) failed, defaulting to \"Virtual printer port for USB\"\n");
  522. wcscpy(pWalk->szPortDescription,L"Virtual printer port for USB");
  523. }
  524. RegCloseKey(hDeviceKey);
  525. hDeviceKey=INVALID_HANDLE_VALUE;
  526. } /*end if re-activated port*/
  527. pWalk->dwDeviceFlags=prDeviceInfo->Flags; //even if we don't need to reload the whole device detail, we need to recheck the flags
  528. }
  529. else
  530. {
  531. pNew=GlobalAlloc(0,sizeof(USBMON_PORT_INFO));
  532. if(pNew==NULL)
  533. return ERROR_NOT_ENOUGH_MEMORY;
  534. wcscpy(pNew->DevicePath,pDeviceDetail->DevicePath);
  535. pNew->iRefCount=0;
  536. hDeviceKey=SetupDiOpenDeviceInterfaceRegKey(hDeviceList,prDeviceInfo,0,KEY_ALL_ACCESS);
  537. if(hDeviceKey==INVALID_HANDLE_VALUE)
  538. {
  539. dwReturn = GetLastError();
  540. OutputDebugStringD1("USBMON: SetupDiOpenDeviceInterfaceRegKey failed\n");
  541. goto Done;
  542. }
  543. dwPortNumberSize=sizeof(dwPortNumber);
  544. dwReturn = RegQueryValueEx(hDeviceKey,L"Port Number",0,NULL,(LPBYTE)&dwPortNumber, &dwPortNumberSize);
  545. if ( dwReturn != ERROR_SUCCESS )
  546. {
  547. OutputDebugStringD2("USBMON: RegQueryValueEx get \"Port Number\" in lAddPrinterToList failed\n");
  548. goto Done;
  549. }
  550. dwStringSize=sizeof(wcPortBaseName);
  551. if(RegQueryValueEx(hDeviceKey,L"Base Name",0,NULL,(LPBYTE)wcPortBaseName,&dwStringSize)!=ERROR_SUCCESS)
  552. {
  553. OutputDebugStringD2("USBMON: RegQueryValueEx, get \"Base Name\" in lAddPrinterToList failed, defaulting to USB\n");
  554. wcscpy(wcPortBaseName,L"USB");
  555. }
  556. vAddNameToBaseNameList(ppBaseNames,wcPortBaseName);
  557. dwStringSize=sizeof(pNew->szPortDescription);
  558. dwReturn=RegQueryValueEx(hDeviceKey,L"Port Description",0,NULL,(LPBYTE)(pNew->szPortDescription),&dwStringSize);
  559. if(dwReturn!=ERROR_SUCCESS)
  560. {
  561. wsprintfA(szDebugBuff,"USBMON: RegQueryValueEx returned (signed) %d, (unsigned) %u\n",dwReturn,dwReturn);
  562. OutputDebugStringD2(szDebugBuff);
  563. OutputDebugStringD2("USBMON: *************************************************RegQueryValueEx, get \"Port Description\" in lAddPrinterToList failed, defaulting to \"Virtual printer port for USB\"\n");
  564. wcscpy(pNew->szPortDescription,L"Virtual printer port for USB");
  565. }
  566. else
  567. {
  568. OutputDebugStringD2("USBMON: *****************************************RegQueryValueEx on baseName OK\n");
  569. }
  570. wsprintf(wcPortName,L"%s%03u",wcPortBaseName,dwPortNumber);
  571. OutputDebugStringD3("USBMON: computed port name ==");
  572. OutputDebugStringWD3(wcPortName);
  573. wcscpy(pNew->szPortName,wcPortName);
  574. pNew->dwDeviceFlags=prDeviceInfo->Flags;
  575. if((pNew->dwDeviceFlags)&SPINT_ACTIVE)
  576. RegDeleteValue(hDeviceKey,L"recyclable");
  577. OutputDebugStringD3("USBMON: AddPrinterToList Start of insertion\n");
  578. pWalk=*ppHead;
  579. if(pWalk==NULL)
  580. {
  581. *ppHead=pNew;
  582. pNew->pNext=NULL;
  583. pNew = NULL;
  584. }
  585. else if(lstrcmp(pNew->szPortName,pWalk->szPortName)<0)
  586. {
  587. OutputDebugStringD3("USBMON: AddPrinterToList New Head\n");
  588. pNew->pNext=*ppHead;
  589. (*ppHead)=pNew;
  590. pNew = NULL;
  591. }
  592. else if(lstrcmp(pNew->szPortName,pWalk->szPortName)==0)
  593. {
  594. pNew->pNext=(*ppHead)->pNext;
  595. (*ppHead)=pNew;
  596. GlobalFree(pWalk);
  597. pNew = NULL;
  598. }
  599. else
  600. {
  601. if(pWalk->pNext!=NULL)
  602. {
  603. iResult=lstrcmp(pNew->szPortName,pWalk->pNext->szPortName);
  604. }
  605. while((iResult>0)&&(pWalk->pNext!=NULL))
  606. {
  607. pWalk=pWalk->pNext;
  608. if(pWalk->pNext!=NULL)
  609. {
  610. iResult=lstrcmp(pNew->szPortName,pWalk->pNext->szPortName);
  611. }
  612. } /*end while*/
  613. if(pWalk->pNext!=NULL)
  614. if(iResult==0) //they match
  615. {
  616. pTemp=pWalk->pNext;
  617. pWalk->pNext=pWalk->pNext->pNext;
  618. GlobalFree(pTemp);
  619. }
  620. pNew->pNext=pWalk->pNext;
  621. pWalk->pNext=pNew;
  622. pNew = NULL;
  623. } /*end else*/
  624. } /*end else pWalk==NULL, therefore it's a new node*/
  625. dwReturn = ERROR_SUCCESS;
  626. Done:
  627. if ( pNew )
  628. GlobalFree(pNew);
  629. if ( hDeviceKey != INVALID_HANDLE_VALUE )
  630. RegCloseKey(hDeviceKey);
  631. return dwReturn;
  632. } /*end function lAddPrinterToList*/
  633. void vAddNameToBaseNameList(PUSBMON_BASENAME *ppBaseNames,WCHAR *wcPortBaseName)
  634. {
  635. BOOL bFound;
  636. PUSBMON_BASENAME pWalk,pNew;
  637. pWalk=*ppBaseNames;
  638. bFound=FALSE;
  639. while((pWalk!=NULL)&&(!bFound))
  640. {
  641. if(wcscmp(pWalk->wcBaseName,wcPortBaseName)==0)
  642. bFound=TRUE;
  643. pWalk=pWalk->pNext;
  644. } /*end while more items*/
  645. if(!bFound)
  646. {
  647. pWalk=*ppBaseNames;
  648. pNew=GlobalAlloc(0,sizeof(USBMON_BASENAME));
  649. if(pNew==NULL)
  650. return;
  651. wcscpy(pNew->wcBaseName,wcPortBaseName);
  652. if(*ppBaseNames==NULL)
  653. {
  654. *ppBaseNames=pNew;
  655. pNew->pNext=NULL;
  656. }
  657. else if(wcscmp(pNew->wcBaseName,pWalk->wcBaseName)<0)
  658. {
  659. pNew->pNext=*ppBaseNames;
  660. *ppBaseNames=pNew;
  661. }
  662. else
  663. {
  664. while((!bFound)&&(pWalk->pNext!=NULL))
  665. {
  666. if(wcscmp(pNew->wcBaseName,pWalk->pNext->wcBaseName)>0)
  667. bFound=TRUE;
  668. else
  669. pWalk=pWalk->pNext;
  670. }
  671. pNew->pNext=pWalk->pNext;
  672. pWalk->pNext=pNew;
  673. } /*end else we need to insert it (not new head)*/
  674. } /*end if need to add*/
  675. } /*end function vAddNameToBaseNameList*/
  676. char *WtoA(WCHAR *pInString)
  677. {
  678. static char szDest[256];
  679. char *pSourceWalk;
  680. char *pszDestWalk;
  681. pszDestWalk=szDest;
  682. pSourceWalk=(char *)pInString;
  683. while(*pSourceWalk!='\0')
  684. {
  685. *(pszDestWalk++)=*pSourceWalk;
  686. pSourceWalk+=2;
  687. }
  688. (*pszDestWalk)='\0';
  689. wsprintfA(szDebugBuff,"USBMON, WtoA, About to return %s\n",szDest);
  690. OutputDebugStringD3(szDebugBuff); //yy
  691. return szDest;
  692. }
  693. void vCleanUpQueuesAndPorts(PUSBMON_PORT_INFO * ppPortInfo,int iNumberOfPorts,PUSBMON_BASENAME pBaseNames)
  694. {
  695. DWORD dwThreadID;
  696. PCLEANUP_THREAD_PARAMS pCleanupParams;
  697. pCleanupParams=(PCLEANUP_THREAD_PARAMS)GlobalAlloc(0,sizeof(CLEANUP_THREAD_PARAMS));
  698. if(pCleanupParams==NULL)
  699. {
  700. OutputDebugStringD1("USBMON: failed to allocate memory in vCleanupQueuesAndPorts\n");
  701. return;
  702. }
  703. pCleanupParams->ppPortInfo=ppPortInfo;
  704. pCleanupParams->iPortCount=iNumberOfPorts;
  705. pCleanupParams->hSemaphore=hMonitorSemaphore;
  706. pCleanupParams->pBaseNames=pBaseNames;
  707. CreateThread(NULL,0,CleanupThread,pCleanupParams,0,&dwThreadID);
  708. }
  709. DWORD WINAPI CleanupThread(LPVOID pParam)
  710. {
  711. PCLEANUP_THREAD_PARAMS pParams;
  712. PUSBMON_QUEUE_INFO pQueueList;
  713. DWORD dwStatus;
  714. pParams=(PCLEANUP_THREAD_PARAMS)pParam;
  715. pQueueList=NULL;
  716. lGetQueues(&pQueueList,pParams->pBaseNames);
  717. if(pQueueList==NULL)
  718. {
  719. OutputDebugStringD3("USBMON: CleanupThread, pQueueList==NULL\n");
  720. }
  721. else
  722. {
  723. OutputDebugStringD3("USBMON: CleanupThread, pQueueList!=NULL\n");
  724. }
  725. wsprintfA(szDebugBuff,"USBMON:+++++++++++++++++++++++++++++++++++++++ Head of CleanupThread, before WaitForSingleObject, hMonitorSemaphore=%x\n",hMonitorSemaphore);
  726. OutputDebugStringD2(szDebugBuff);
  727. dwStatus=WaitForSingleObject(hMonitorSemaphore,INFINITE);
  728. if(dwStatus==WAIT_FAILED)
  729. OutputDebugStringD1("USBMON: WaitForSingleObject failed!\n");
  730. wsprintfA(szDebugBuff,"USBMON: CleanupThread: WaitForSingleObject returned %d\n",dwStatus);
  731. OutputDebugStringD3(szDebugBuff);
  732. OutputDebugStringD2("USBMON: Head of CleanupThread, after WaitForSingleObject\n");
  733. vEliminateOldQueuesAndPorts(pQueueList,pParams->ppPortInfo);
  734. vDestroyQueueList(pQueueList);
  735. GlobalFree(pParams);
  736. OutputDebugStringD2("USBMON: tail of CleanupThread, about to release semaphore++++++++++++++++++++++++++++++++++++++++++++\n");
  737. iCleanupThreads--;
  738. ReleaseSemaphore(hMonitorSemaphore,1,NULL);
  739. return 0;
  740. }
  741. void vEliminateOldQueuesAndPorts(PUSBMON_QUEUE_INFO pQueueInfo,PUSBMON_PORT_INFO * ppPortHead)
  742. {
  743. PUSBMON_QUEUE_INFO pQueueWalk;
  744. PUSBMON_PORT_INFO pPortWalk;
  745. HDEVINFO hDevInfo;
  746. int iCompare;
  747. BOOL bNull=FALSE;
  748. hDevInfo=SetupDiGetClassDevs((GUID *)&USB_PRINTER_GUID,NULL,NULL,DIGCF_INTERFACEDEVICE);
  749. if ( hDevInfo == INVALID_HANDLE_VALUE )
  750. return;
  751. pQueueWalk=pQueueInfo;
  752. pPortWalk= *ppPortHead;
  753. pPortWalk=*ppPortHead;
  754. if((pPortWalk!=NULL)&&(pQueueWalk!=NULL))
  755. {
  756. iCompare=lstrcmp(pPortWalk->szPortName,pQueueWalk->wcPortName);
  757. wsprintf((WCHAR *)szDebugBuff,L"USBMON: About to compare %s and %s\n",pPortWalk->szPortName,pQueueWalk->wcPortName);
  758. OutputDebugStringWD2((WCHAR *)szDebugBuff);
  759. }
  760. else
  761. bNull=TRUE;
  762. while(!bNull)
  763. {
  764. //Walk through matching items loop
  765. while((iCompare==0)&&(!bNull))
  766. {
  767. wsprintfA(szDebugBuff,"USBMON: in cleanup loop, flags=%d\n",pPortWalk->dwDeviceFlags);
  768. OutputDebugStringD2(szDebugBuff);
  769. if((pPortWalk->dwDeviceFlags)&SPINT_ACTIVE)
  770. vUnGreyQueue(pQueueWalk);
  771. else
  772. vGreyOutQueue(pQueueWalk);
  773. pPortWalk=pPortWalk->pNext;
  774. pQueueWalk=pQueueWalk->pNext;
  775. if((pPortWalk!=NULL)&&(pQueueWalk!=NULL))
  776. {
  777. iCompare=lstrcmp(pPortWalk->szPortName,pQueueWalk->wcPortName);
  778. } /*end if no nulls*/
  779. else
  780. bNull=TRUE;
  781. } /*end while matching items*/
  782. // grey out "detached" printers loop
  783. while((iCompare>0)&&(!bNull))
  784. {
  785. OutputDebugStringD3("USBMON: About to grey out queue inside the \"grey queue\" inner loop\n");
  786. //vGreyOutQueue(pQueueWalk); //perhaps something else should happen here. What does it mean if a port is gone but the queue is still around?
  787. pQueueWalk=pQueueWalk->pNext;
  788. if(pQueueWalk!=NULL)
  789. {
  790. wsprintf((WCHAR *)szDebugBuff,L"USBMON: About to compare %s and %s\n",pPortWalk->szPortName,pQueueWalk->wcPortName);
  791. OutputDebugStringWD2((WCHAR *)szDebugBuff);
  792. iCompare=lstrcmp(pPortWalk->szPortName,pQueueWalk->wcPortName);
  793. }
  794. else
  795. bNull=TRUE;
  796. } /*end grey out loop*/
  797. // delete orphaned port names loop
  798. while((iCompare<0)&&(!bNull))
  799. {
  800. if(!((pPortWalk->dwDeviceFlags)&SPINT_ACTIVE))
  801. vDeletePort(pPortWalk, hDevInfo);
  802. pPortWalk=pPortWalk->pNext;
  803. if(pPortWalk!=NULL)
  804. {
  805. wsprintf((WCHAR *)szDebugBuff,L"USBMON: About to compare %s and %s\n",pPortWalk->szPortName,pQueueWalk->wcPortName);
  806. OutputDebugStringWD2((WCHAR *)szDebugBuff);
  807. iCompare=lstrcmp(pPortWalk->szPortName,pQueueWalk->wcPortName);
  808. }
  809. else
  810. bNull=TRUE;
  811. } /*end delete ports loop*/
  812. } /*end while both lists not null (outer loop)*/
  813. //grey out "detached" printers at end of list loop
  814. while(pQueueWalk!=NULL)
  815. {
  816. OutputDebugStringD2("USBMON: About to grey out queue inside the \"grey queue\" cleanup loop\n");
  817. vGreyOutQueue(pQueueWalk); //perhaps something else should happen here. What does it mean if a port is gone but the queue is still around?
  818. pQueueWalk=pQueueWalk->pNext;
  819. } //end end of list disable queues list
  820. //delete orphaned ports names at end of list loop
  821. while(pPortWalk!=NULL)
  822. {
  823. if(!((pPortWalk->dwDeviceFlags)&SPINT_ACTIVE))
  824. vDeletePort(pPortWalk, hDevInfo);
  825. pPortWalk=pPortWalk->pNext;
  826. } //end end of list delete ports loop
  827. SetupDiDestroyDeviceInfoList(hDevInfo);
  828. } /*end function vEliminateOldQueuesAndPorts*/
  829. void vGreyOutQueue(PUSBMON_QUEUE_INFO pQueue)
  830. {
  831. #define SET_PRINTER_BUFFER_SIZE 1024
  832. HANDLE hPrinterHandle;
  833. PRINTER_DEFAULTS rPrinterDefaults;
  834. BYTE bPrinterInfo[SET_PRINTER_BUFFER_SIZE];
  835. int iSizeNeeded;
  836. PRINTER_INFO_5 *pPrinterInfo;
  837. wsprintfW((WCHAR *)szDebugBuff,L"USBMON: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GreyOut Queue %s attached to %s\n",pQueue->wcPrinterName,pQueue->wcPortName);
  838. OutputDebugStringWD2((WCHAR *)szDebugBuff);
  839. rPrinterDefaults.pDatatype=NULL;
  840. rPrinterDefaults.pDevMode=NULL;
  841. rPrinterDefaults.DesiredAccess=PRINTER_ACCESS_ADMINISTER|STANDARD_RIGHTS_ALL|SPECIFIC_RIGHTS_ALL;
  842. if(!OpenPrinter(pQueue->wcPrinterName,&hPrinterHandle,&rPrinterDefaults))
  843. OutputDebugStringD1("USBMON: Unable to OpenPrinter in vGreyOutQueue\n");
  844. if(!GetPrinter(hPrinterHandle,5,bPrinterInfo,SET_PRINTER_BUFFER_SIZE,&iSizeNeeded))
  845. {
  846. wsprintfA(szDebugBuff,"USBMON: GetPrinter failed, error code==%d\n",GetLastError());
  847. OutputDebugStringD1(szDebugBuff);
  848. }
  849. if(iSizeNeeded>SET_PRINTER_BUFFER_SIZE)
  850. OutputDebugStringD1("USBMON: Buffer size not big enough in vGreyOutQueue\n");
  851. pPrinterInfo=(PRINTER_INFO_5 *)bPrinterInfo;
  852. (pPrinterInfo->Attributes)|=PRINTER_ATTRIBUTE_WORK_OFFLINE;
  853. OutputDebugStringD2("USBMON: about to SetPrinter\n");
  854. if(!SetPrinter(hPrinterHandle,5,bPrinterInfo,0))
  855. {
  856. wsprintfA(szDebugBuff,"USBMON: SetPrinter failed, error code==%d\n",GetLastError());
  857. OutputDebugStringD1(szDebugBuff);
  858. }
  859. ClosePrinter(hPrinterHandle);
  860. } /*end function vGreyOutQueue*/
  861. void vUnGreyQueue(PUSBMON_QUEUE_INFO pQueue)
  862. {
  863. HANDLE hPrinterHandle;
  864. PRINTER_DEFAULTS rPrinterDefaults;
  865. BYTE bPrinterInfo[SET_PRINTER_BUFFER_SIZE];
  866. int iSizeNeeded;
  867. PRINTER_INFO_5 *pPrinterInfo;
  868. wsprintfW((WCHAR *)szDebugBuff,L"USBMON: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UnGrey Queue %s attached to %s\n",pQueue->wcPrinterName,pQueue->wcPortName);
  869. OutputDebugStringWD3((WCHAR *)szDebugBuff);
  870. rPrinterDefaults.pDatatype=NULL;
  871. rPrinterDefaults.pDevMode=NULL;
  872. rPrinterDefaults.DesiredAccess=PRINTER_ACCESS_ADMINISTER|STANDARD_RIGHTS_ALL|SPECIFIC_RIGHTS_ALL;
  873. if(!OpenPrinter(pQueue->wcPrinterName,&hPrinterHandle,&rPrinterDefaults))
  874. OutputDebugStringD1("USBMON: Unable to OpenPrinter in vGreyOutQueue\n");
  875. if(!GetPrinter(hPrinterHandle,5,bPrinterInfo,SET_PRINTER_BUFFER_SIZE,&iSizeNeeded))
  876. {
  877. wsprintfA(szDebugBuff,"USBMON: GetPrinter failed, error code==%d\n",GetLastError());
  878. OutputDebugStringD1(szDebugBuff);
  879. }
  880. if(iSizeNeeded>SET_PRINTER_BUFFER_SIZE)
  881. OutputDebugStringD1("USBMON: Buffer size not big enough in vUnGreyQueue\n");
  882. pPrinterInfo=(PRINTER_INFO_5 *)bPrinterInfo;
  883. (pPrinterInfo->Attributes)&=(~PRINTER_ATTRIBUTE_WORK_OFFLINE);
  884. OutputDebugStringD3("USBMON: about to SetPrinter\n");
  885. if(!SetPrinter(hPrinterHandle,5,bPrinterInfo,0))
  886. {
  887. wsprintfA(szDebugBuff,"USBMON: SetPrinter failed, error code==%d\n",GetLastError());
  888. OutputDebugStringD1(szDebugBuff);
  889. }
  890. ClosePrinter(hPrinterHandle);
  891. } /*end function vUnGreyQueue*/
  892. /*******************************************
  893. * vDletePort -- marks a port struct as *
  894. * Deleted by setting it's device name to *
  895. * Null and deleting the port name value *
  896. * from the registry *
  897. *******************************************/
  898. void vDeletePort(PUSBMON_PORT_INFO pPort, HDEVINFO hDeviceList)
  899. {
  900. HANDLE hDeviceKey;
  901. // DebugBreak();
  902. wsprintfW((WCHAR *)szDebugBuff,L"USBMON: /********************Head of vDeletePort for %s.\n",pPort->szPortName);
  903. OutputDebugStringWD2((WCHAR *)szDebugBuff);
  904. hDeviceKey=hGetPortRegKey(pPort, hDeviceList);
  905. if(hDeviceKey!=INVALID_HANDLE_VALUE)
  906. {
  907. wsprintfW((WCHAR *)szDebugBuff,L"USBMON: Opened key for port %s.\n",pPort->szPortName);
  908. OutputDebugStringWD3((WCHAR *)szDebugBuff);
  909. // if(RegDeleteValue(hDeviceKey,L"Port Number")==ERROR_SUCCESS)
  910. if(RegSetValueEx(hDeviceKey,L"recyclable",0,REG_NONE,0,0)==ERROR_SUCCESS)
  911. {
  912. OutputDebugStringD3("USBMON: RegSetValue Success\n");
  913. }
  914. else
  915. {
  916. OutputDebugStringD2("USBMON: RegSetValue Failure\n");
  917. }
  918. RegCloseKey(hDeviceKey);
  919. } /*end if hGetProtRegKey worked*/
  920. else
  921. {
  922. wsprintfW((WCHAR *)szDebugBuff,L"USBMON: Unable to locate and delete reg key for %s\n",pPort->szPortName);
  923. OutputDebugStringWD1((WCHAR *)szDebugBuff);
  924. }
  925. } /*end function vDeletePort*/
  926. BOOL
  927. MatchingRegKey(
  928. HKEY hKey,
  929. PUSBMON_PORT_INFO pPort
  930. )
  931. {
  932. WCHAR wcBaseName[MAX_PORT_LEN];
  933. WCHAR wcPortName[MAX_PORT_LEN];
  934. DWORD dwPortNumber;
  935. DWORD dwReadSize;
  936. dwReadSize=sizeof(DWORD);
  937. if(RegQueryValueEx(hKey,L"Port Number",0,NULL,(LPBYTE)&dwPortNumber,&dwReadSize)==ERROR_SUCCESS)
  938. {
  939. dwReadSize=sizeof(wcBaseName);
  940. if(RegQueryValueEx(hKey,L"Base Name",0,NULL,(LPBYTE)wcBaseName,&dwReadSize)!=ERROR_SUCCESS)
  941. {
  942. OutputDebugStringD2("USBMON: Unable to locate basename. Defaulting to \"USB\"\n"); //yy
  943. wcscpy(wcBaseName,L"USB");
  944. }
  945. wsprintf(wcPortName,L"%s%03u",wcBaseName,dwPortNumber);
  946. return wcscmp(wcPortName,pPort->szPortName)==0;
  947. }
  948. return 0;
  949. }
  950. HANDLE hGetPortRegKey(PUSBMON_PORT_INFO pPort, HDEVINFO hDeviceList)
  951. {
  952. GUID *pPrinterGuid;
  953. int iLoop=0;
  954. SP_DEVICE_INTERFACE_DATA rDeviceInfo;
  955. BOOL bMoreDevices,bFound=FALSE;
  956. DWORD dwRequiredSize;
  957. HANDLE hRegHandle;
  958. PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceDetail;
  959. WCHAR wcBaseName[MAX_PORT_LEN];
  960. rDeviceInfo.cbSize=sizeof(rDeviceInfo);
  961. if ( !SetupDiOpenDeviceInterface(hDeviceList, pPort->DevicePath,
  962. DIODI_NO_ADD, &rDeviceInfo) )
  963. return INVALID_HANDLE_VALUE;
  964. hRegHandle = SetupDiOpenDeviceInterfaceRegKey(hDeviceList,
  965. &rDeviceInfo,
  966. 0,
  967. KEY_ALL_ACCESS);
  968. if ( hRegHandle != INVALID_HANDLE_VALUE ) {
  969. if ( MatchingRegKey(hRegHandle, pPort) )
  970. return hRegHandle;
  971. CloseHandle(hRegHandle);
  972. }
  973. pPrinterGuid=(GUID *)&USB_PRINTER_GUID;
  974. bMoreDevices=SetupDiEnumDeviceInterfaces(hDeviceList,0,pPrinterGuid,iLoop,&rDeviceInfo);
  975. while((bMoreDevices)&&(!bFound))
  976. {
  977. SetupDiGetDeviceInterfaceDetail(hDeviceList,&rDeviceInfo,NULL,0,&dwRequiredSize,NULL);
  978. pDeviceDetail=(PSP_DEVICE_INTERFACE_DETAIL_DATA)GlobalAlloc(0,dwRequiredSize);
  979. if(pDeviceDetail==NULL)
  980. {
  981. OutputDebugStringD1("USBMON: Unable to allocate memory in pGetPrinterList\n");
  982. return INVALID_HANDLE_VALUE;
  983. }
  984. pDeviceDetail->cbSize=sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  985. if(!SetupDiGetDeviceInterfaceDetail(hDeviceList,&rDeviceInfo,pDeviceDetail,dwRequiredSize,&dwRequiredSize,NULL))
  986. {
  987. OutputDebugStringD1("USBMON: SetupDiGetDeviceInterfaceDetail (second call) failed\n");
  988. return INVALID_HANDLE_VALUE;
  989. } /*end if SetupDiGetDeviceInterfaceDetail, call2 failed*/
  990. hRegHandle=SetupDiOpenDeviceInterfaceRegKey(hDeviceList,&rDeviceInfo,0,KEY_ALL_ACCESS);
  991. if(hRegHandle!=INVALID_HANDLE_VALUE)
  992. {
  993. if ( MatchingRegKey(hRegHandle, pPort) )
  994. bFound=TRUE;
  995. else
  996. CloseHandle(hRegHandle);
  997. } /*end if SetupDiOpenDeviceInterfaceRegKey successful*/
  998. GlobalFree(pDeviceDetail);
  999. bMoreDevices=SetupDiEnumDeviceInterfaces(hDeviceList,0,pPrinterGuid,++iLoop,&rDeviceInfo);
  1000. } /*end while more devices & !found*/
  1001. if(!bFound)
  1002. hRegHandle=INVALID_HANDLE_VALUE;
  1003. return hRegHandle;
  1004. } /*end function hGetPortRegKey*/