2014년 10월 29일 수요일

프린터 출력 모니터링 함수

DWORD WatchPrintProc(LPVOID lpdata)

{

PPRINTER_NOTIFY_INFO pNotification = NULL;



WORD JobFields[] =

    {

        JOB_NOTIFY_FIELD_PRINTER_NAME,

        JOB_NOTIFY_FIELD_MACHINE_NAME,

        JOB_NOTIFY_FIELD_PORT_NAME,

        JOB_NOTIFY_FIELD_USER_NAME,

        JOB_NOTIFY_FIELD_NOTIFY_NAME,

        JOB_NOTIFY_FIELD_DATATYPE,

        JOB_NOTIFY_FIELD_PRINT_PROCESSOR,

        JOB_NOTIFY_FIELD_PARAMETERS,

        JOB_NOTIFY_FIELD_DRIVER_NAME,

        JOB_NOTIFY_FIELD_DEVMODE,

        JOB_NOTIFY_FIELD_STATUS,

        JOB_NOTIFY_FIELD_STATUS_STRING,

        JOB_NOTIFY_FIELD_DOCUMENT,

        JOB_NOTIFY_FIELD_PRIORITY,

        JOB_NOTIFY_FIELD_POSITION,

        JOB_NOTIFY_FIELD_SUBMITTED,

        JOB_NOTIFY_FIELD_START_TIME,

        JOB_NOTIFY_FIELD_UNTIL_TIME,

        JOB_NOTIFY_FIELD_TIME,

        JOB_NOTIFY_FIELD_TOTAL_PAGES,

        JOB_NOTIFY_FIELD_PAGES_PRINTED,

        JOB_NOTIFY_FIELD_TOTAL_BYTES,

        JOB_NOTIFY_FIELD_BYTES_PRINTED

    };

PRINTER_NOTIFY_OPTIONS_TYPE Notifications[1] =

    {

        {

            JOB_NOTIFY_TYPE,

            0,

            0,

            0,

            sizeof(JobFields) / sizeof(JobFields[0]),

            JobFields

        },

    };

PRINTER_NOTIFY_OPTIONS NotificationOptions =

    {

        2,

        PRINTER_NOTIFY_OPTIONS_REFRESH,

        sizeof(Notifications) / sizeof(Notifications[0]),

        Notifications

    };





LPSTR pszTitle =  NULL ;

LPSTR pszName = NULL ;

LPSTR pszShareName = NULL ;

int * pCmdtCode = NULL ;



switch( (int)lpdata )

{

case 0 :

pszTitle = g_WatchPrint.szTitle1 ;

pszName = g_WatchPrint.szName1 ;

pszShareName = g_WatchPrint.szShare1 ;

pCmdtCode = &g_WatchPrint.nCmdtCode1 ;

break ;

case 1 :

pszTitle = g_WatchPrint.szTitle2 ;

pszName = g_WatchPrint.szName2 ;

pszShareName = g_WatchPrint.szShare2 ;

pCmdtCode = &g_WatchPrint.nCmdtCode2 ;

break ;



default :

return 0 ;

}



if( !pszTitle || !pszShareName || !pCmdtCode || !pszName )

return 0 ;







if( !strlen( pszTitle ) )

return 0;







std::map<int,int> MapId ;

HANDLE hPrinter = NULL;

while(TRUE){





DWORD dwNeeded = NULL,

dwReturned = NULL;



// CString strPrinter = "HP LaserJet P2035";

// CString strPrinter = "PC01에서 자동 EPSON Stylus Photo R210 Series";

// CString strPrinter = g_WatchPrint.szPrintName1 ;

CString strPrinter;

EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 1, NULL, 0, &dwNeeded, &dwReturned) ;



if( dwNeeded <= 0 ){

CDebug::dprintf( "Failed EnumPrinters\n" ) ;

return 0 ;

}

// CDebug::dprintf( "EnumPrinter( %d , %d )\n" , dwNeeded , dwReturned ) ;

 

LPBYTE lpBuffer = new BYTE[dwNeeded];

EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 1, lpBuffer, dwNeeded, &dwNeeded, &dwReturned);



CDebug::dprintf( "EnumPrinter( %d , %d )\n" , dwNeeded , dwReturned ) ;



PPRINTER_INFO_1 p1 = (PPRINTER_INFO_1) lpBuffer;







for (DWORD x = 0; x < dwReturned; x++)

{

// CDebug::dprintf("EnumPrinter(%d) (%s-%s)\n", dwReturned , p1->pName , g_WatchPrint.szTitle1) ;



//

// 공유된 프린터 라면 공유 이름으로 프린터를 찾는다.

if( strlen( pszShareName )){

OpenPrinter((LPTSTR) (LPCTSTR) p1->pName, &hPrinter, NULL);



if( !hPrinter )

continue ;



BOOL IsFind  = FALSE ;

DWORD dwNeeded = ::DocumentProperties(NULL, hPrinter, (LPTSTR) (LPCTSTR) p1->pName, NULL, NULL, 0) ;



::GetPrinter(hPrinter, 2, 0, 0, &dwNeeded);

PRINTER_INFO_2 *pi2 = (PRINTER_INFO_2  *)::GlobalAlloc(GPTR,dwNeeded);

GetPrinter(hPrinter, 2, (LPBYTE)pi2, dwNeeded, &dwNeeded);





CDebug::dprintf( "Printer - DriverName=%s - %s , ShareName=%s - %s \n" , pi2->pDriverName , pszName , pi2->pShareName , pszShareName ) ;

if( strcmp( pi2->pDriverName , pszName ) == 0 && strcmp( pi2->pShareName , pszShareName ) == 0 ){

IsFind = TRUE ;

strPrinter = p1->pName ;

}





::GlobalFree(pi2) ;



if( IsFind )

break ;



ClosePrinter( hPrinter ) ;

}

else if( strstr( p1->pName , pszTitle ) ){ // 공유된 프린터가 아니라면( 네트웍프린터 ) 프린터 타이틀로 프린터를 찾는다.

strPrinter = p1->pName ;

OpenPrinter((LPTSTR) (LPCTSTR) strPrinter, &hPrinter, NULL);

break ;

}

p1++;

}

delete lpBuffer;





if( strPrinter.IsEmpty() )

return 0;





// HANDLE hPrinter;

// OpenPrinter((LPTSTR) (LPCTSTR) strPrinter, &hPrinter, NULL);





if( !hPrinter )

return 0;



// get a handle to a printer change notification object.

HANDLE hChange = FindFirstPrinterChangeNotification(hPrinter,

PRINTER_CHANGE_ALL,

0,

&NotificationOptions);



DWORD dwChange;

HANDLE aHandles[2];

aHandles[0] = hChange;





::GetPrinter(hPrinter, 2, 0, 0, &dwNeeded);

PRINTER_INFO_2 *pi2 = (PRINTER_INFO_2  *)::GlobalAlloc(GPTR,dwNeeded);

::GetPrinter(hPrinter, 2, (LPBYTE)pi2, dwNeeded, &dwNeeded);





if( /*strncmp( pi2->pPortName , "\\\\" , strlen( "\\\\" ) ) == 0 || strncmp( pi2->pPortName , "IP" , strlen( "IP" ) ) == 0 ||*/ ( pi2->pServerName && strlen(pi2->pServerName) ) ){

CDebug::dprintf("==========================================================\n");

CDebug::dprintf("It is Not Local Printer1(%s) \n", strPrinter );

CDebug::dprintf("==========================================================\n");



FindClosePrinterChangeNotification(hChange);

hChange = INVALID_HANDLE_VALUE;

ClosePrinter( hPrinter );

hPrinter = NULL ;

return 0;

}





// Office 레지 등록 (워드 카피수 오류 수정)

CRegistry reg;

if (reg.Open(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Office\\11.0\\Word\\Options", KEY_ALL_ACCESS)){ // 2003

DWORD dwReadData = 0 ;

reg.ReadDWORD("ForceSetCopyCount" , dwReadData ) ;

if( dwReadData != 1 )

reg.WriteDWORD("ForceSetCopyCount",1) ;

reg.Close() ;

}

if (reg.Open(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Office\\12.0\\Word\\Options", KEY_ALL_ACCESS)){ // 2007

DWORD dwReadData = 0 ;

reg.ReadDWORD("ForceSetCopyCount" , dwReadData ) ;

if( dwReadData != 1 )

reg.WriteDWORD("ForceSetCopyCount",1) ;

reg.Close() ;

}

if (reg.Open(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Office\\14.0\\Word\\Options", KEY_ALL_ACCESS)){ //2010

DWORD dwReadData = 0 ;

reg.ReadDWORD("ForceSetCopyCount" , dwReadData ) ;

if( dwReadData != 1 )

reg.WriteDWORD("ForceSetCopyCount",1) ;

reg.Close() ;

}







CDebug::dprintf("==========================================================\n");

CDebug::dprintf("WatchPrint1 - Build(06-09) - (%s) \n", strPrinter );

CDebug::dprintf("==========================================================\n");









MapId.clear() ;

while (hChange != INVALID_HANDLE_VALUE)

{

// sleep until a printer change notification wakes this thread or the

// event becomes set indicating it's time for the thread to end.

WaitForMultipleObjects(2, aHandles, FALSE, INFINITE);



if (WaitForSingleObject(hChange, 0U) == WAIT_OBJECT_0)

{

FindNextPrinterChangeNotification(hChange, &dwChange, &NotificationOptions, (LPVOID *) &pNotification);



if (pNotification != NULL)

{

// if a notification overflow occurred,

if (pNotification->Flags & PRINTER_NOTIFY_INFO_DISCARDED)

{

DWORD dwOldFlags = NotificationOptions.Flags;



// we must refresh to continue

NotificationOptions.Flags = PRINTER_NOTIFY_OPTIONS_REFRESH;



FreePrinterNotifyInfo(pNotification);



FindNextPrinterChangeNotification(hChange, &dwChange, &NotificationOptions, (LPVOID *) &pNotification);



NotificationOptions.Flags = dwOldFlags;

}







// int nbeganTime = 0 ;

int nStatus = NULL;

int nCopies = 0 ;

int nCopies1 = 0 ;

int nId = 0 ;

// BOOL IsLocal = FALSE ;



// CDebug::dprintf("WatchPrint1 - Notifi (%d) \n", pNotification->Count );

// iterate through each notification

int nTotalPages = 0 ;

int nTotalPages1 = 0 ;

BOOL bNewDataID = FALSE ;

char szComName[40] = {0,} ;

for (DWORD x = 0; x < pNotification->Count; x++)

{

ASSERT(pNotification->aData[x].Type == JOB_NOTIFY_TYPE);





if( pNotification->aData[x].Id ){

nId = pNotification->aData[x].Id ;





if (pNotification->aData[x].Field == JOB_NOTIFY_FIELD_TOTAL_PAGES){

nTotalPages1 = pNotification->aData[x].NotifyData.adwData[0];

// CDebug::dprintf("JOB_NOTIFY_FIELD_TOTAL_PAGES(%d) \n", nTotalPages1 );

}else if (pNotification->aData[x].Field == JOB_NOTIFY_FIELD_STATUS){

TRACE( "JOB_NOTIFY_FIELD_STATUS ( %d )\n" , pNotification->aData[x].NotifyData.adwData[0] ) ;

/*if( pNotification->aData[x].NotifyData.adwData[0] == JOB_STATUS_PRINTED ){



}

else*/ if( nStatus != JOB_STATUS_PRINTED || nStatus != JOB_STATUS_PRINTING ){

nStatus = pNotification->aData[x].NotifyData.adwData[0];



if( nStatus == JOB_STATUS_PRINTING || nStatus == JOB_STATUS_PRINTED ){



if( MapId.find( nId ) == MapId.end() ){



if( nCopies == 0 ){

/* for( int i = 0 ; i < 6 ; i++ ){

CSpoolReader reader( strPrinter , nId ) ;

nCopies = reader.GetCopies() ;

if( nCopies > 0 )

break ;



Sleep( 400 ) ;

}*/





JOB_INFO_2 *pd_JobInfo = NULL;

DWORD dwNeed = NULL ;

DWORD dwJobId = NULL ;

DWORD dwRet = NULL ;

if( GetJob( hPrinter,nId , 2, NULL , NULL, &dwNeeded) ){

pd_JobInfo = (JOB_INFO_2 *)malloc(dwNeeded);



if( GetJob( hPrinter, nId, 2, (LPBYTE)pd_JobInfo , dwNeeded , &dwRet) ){

nTotalPages = pd_JobInfo->PagesPrinted + pd_JobInfo->TotalPages ;

if( nCopies < 1 ){

DEVMODE *pDevMode = pd_JobInfo->pDevMode;

nCopies = pDevMode->dmCopies ;

}

}

free(pd_JobInfo) ;

}





}

CDebug::dprintf( "Printer page copies (%d)\n" , nCopies ) ;

bNewDataID = TRUE ;

}



}

}





}

else if (pNotification->aData[x].Field == JOB_NOTIFY_FIELD_DEVMODE){

DEVMODE DMode ;

memcpy( &DMode, (void*)pNotification->aData[x].NotifyData.adwData[1], sizeof DMode ) ;

nCopies1 = DMode.dmCopies ; // 인쇄 매수

CDebug::dprintf( "Printer page copies1 (%d)\n" , nCopies ) ;



}

else if ( pNotification->aData[x].Field == JOB_NOTIFY_FIELD_MACHINE_NAME ){

LPSTR pszSendComName = (LPSTR)pNotification->aData[x].NotifyData.Data.pBuf ;

if( pszSendComName[0] == '\\' && pszSendComName[1] == '\\' )

STRnCPY( szComName , &pszSendComName[2] ) ;

else

STRnCPY( szComName , pszSendComName ) ;



/* char szComName[MAX_PATH] ;

DWORD dwSize = MAX_PATH ;

GetComputerName( szComName , &dwSize ) ;



TCHAR szIP[100] = {0,} ;

DWORD dwip = GetHostIPAddr();

CFNUtil fn;

STRnCPY(szIP, fn.LipToSip(dwip, TRUE));



// 자기 자신이 보낸게 아니라면 무시한다.

// 보낸곳이 로컬이라면 저장 과금 한다. ( "\\kky"로 시작 한다면 "\\" 빼주고 비교 한다. )

if( pszSendComName[0] == '\\' && pszSendComName[1] == '\\' ){

if( strcmp( &pszSendComName[2] , szComName ) == 0 ) // 컴 이름

IsLocal = TRUE ;

else if( strcmp( &pszSendComName[2] , szIP ) == 0 ) // ip 체크

IsLocal = TRUE ;

}

else{

if( strcmp( pszSendComName , szComName ) == 0 ) // 컴 이름

IsLocal = TRUE ;

else if( strcmp( pszSendComName , szIP ) == 0 ) // ip 체크

IsLocal = TRUE ;

}

*/





}









// CDebug::dprintf("Notification->Count(%d , %d) \n", nId , x );



if( nStatus == JOB_STATUS_PRINTED || nStatus == JOB_STATUS_PRINTING){



if( nCopies < 1 && nCopies1 > 0 )

nCopies = nCopies1 ;



if( nTotalPages < 1 && nTotalPages1 > 0 )

nTotalPages = nTotalPages1 ;



CDebug::dprintf("JOB_STATUS_PRINTING - Pages(%d) - Copies(%d) \n", nTotalPages , nCopies );

nTotalPages *= nCopies ;

if( nTotalPages > 0 ){

// if( MapId.find( pNotification->aData[x].Id ) == MapId.end() ){

if( bNewDataID ){

MapId.insert( std::make_pair(pNotification->aData[x].Id ,pNotification->aData[x].Id ) ) ;



// if( IsLocal ){



// CString sLog ;

// sLog.Format( "BillingPrint - Printer(%s) - Pages(%d) - Cmdt(%d) - ComName(%s)\n", pszName , nTotalPages , *pCmdtCode , szComName ) ;

// CDebug::dprintf("BillingPrint - Pages(%d) - Cmdt(%d) - ComName(%s)\n", nTotalPages , *pCmdtCode , szComName );

// UM_WRITE_ERROR_LOG(sLog);



if( nTotalPages > 0 && *pCmdtCode > 0 && strlen( szComName ) ){

// 서버로 출력되었다고 보낸다.

_ReqBillingPrint pkt; ZERO_MEM(pkt);

INIT_TCP_CHNL_BOOL(BILLING_R_, cmdReqBillingPrint);

pkt.nTotalPages = nTotalPages ;

pkt.nCmdtCode = *pCmdtCode ;

STRnCPY( pkt.szComName , szComName ) ;

BOOL result = TcpClt.SendPacket(&pkt, sizeof(pkt));





}

// }









}

/* if( nStatus == JOB_STATUS_PRINTED ){

::GetPrinter(hPrinter, 2, 0, 0, &dwNeeded);

PRINTER_INFO_2 *pi2 = (PRINTER_INFO_2  *)::GlobalAlloc(GPTR,dwNeeded);

GetPrinter(hPrinter, 2, (LPBYTE)pi2, dwNeeded, &dwNeeded);





// 인쇄된 프린터 보관 이라면 취소를 날려 출력로그를 없앤다.

if( (pi2->Attributes&PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS)==PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS ){

CDebug::dprintf("JOB_STATUS_PRINTED\n" );

// 프린트 된것은 취소를 날려 출력로그를 없앤다.

JOB_INFO_2 *pd_JobInfo = NULL;

DWORD dwNeed = NULL ;

DWORD dwJobId = NULL ;

DWORD dwRet = NULL ;

GetJob( hPrinter,pNotification->aData[x].Id , 2, (LPBYTE)pd_JobInfo , NULL, &dwNeeded);

pd_JobInfo = (JOB_INFO_2 *)malloc(dwNeeded);

GetJob( hPrinter, pNotification->aData[x].Id, 2, (LPBYTE)pd_JobInfo , dwNeeded , &dwRet);

SetJob( hPrinter , pNotification->aData[x].Id , 2  , (LPBYTE)pd_JobInfo , JOB_CONTROL_CANCEL ) ;

free(pd_JobInfo) ;

}



::GlobalFree(pi2) ;

}*/





nStatus = NULL ;

}

}



}



}







}



FreePrinterNotifyInfo(pNotification);

pNotification = NULL;







}



//

// 요금 부과할 프린터를 바꾸었다면 기존 셋팅을 초기화 하고 다시 셋팅 하여야 한다.

if( !strlen( pszTitle ) || !strstr( strPrinter , pszTitle ) || *pCmdtCode < 1 || m_bWatchPrintProcQuit ){

FindClosePrinterChangeNotification(hChange);

hChange = INVALID_HANDLE_VALUE;

ClosePrinter( hPrinter );

hPrinter = NULL ;



break ;

}

::Sleep(5) ;



} // while





if( !strlen( pszTitle ) || *pCmdtCode < 1 || m_bWatchPrintProcQuit )

break ;



Sleep( 1000 * 5 ) ;



}// while





return 0;

}

댓글 없음: