본문 바로가기
기타

Printing Architecture

by WeZZ 2012. 2. 28.

출처 : http://www.codeproject.com/useritems/wpa.asp

Printing Architecture

Introduction

Printing 아키텍처는 윈도우즈 아키텍처에서 가장 중요한 컴포넌트 중의 하나이다. 프린터 스풀러와 프린터 드라이버들로 구성된다. 어플리케이션은 프린트 작업을 생성할 수 있고 디바이스 독립적인 Win32 printing and GDI 함수들을 호출함으로써 프린터에 전달할 수 있다. 프린터 드라이버는 사용자가 프린터의 선택적인 옵션들(용지 사이즈, 출력 매수, Coloration, Pages per sheet 등)을 제어할 수 있는 UI 컴포넌트를 포함하고 있다.

Win32 GDI 함수에대한 어플리케이션의 호출은 GDI 그래픽 엔진으로 전달된다, enhanced metafile (EMF)또는 프린터 드라이버와 함께 조합함으로서 그리는 작업을 스풀하거나 또는 스풀러에게 전달할 수 있는 프린트 가능한 이미지를 렌더링하는. 스풀러 컴포넌트는 EMF 파일을 해석하고 페이지 레이아웃 정보를 삽입할 수 있고 데이터 스트림에 작업 제어 명령을 추가할 수 있다. 스풀러는 프린터의 입출력 포트에 연결된 시리얼, 패러럴, 네트워크 포트 드라이버에 데이터 스트림을 보낸다. 스풀러와 드라이버 컴포넌트는 교체 가능하도록 설계되었다. 새로운 프린터를 지원하기 위해서는 Microsoft에서 제공하는 프린터 드라이버 중의 하나를 사용해서 새로운 데이터 파일을 생성하기만 하면 된다.

대부분의 디바이스 드라이버의 대부분은 커널 모드에서 작동한다. 몇가지의 디바이스 드라이버 또는 일부만이 사용자 모드와 커널 모드에서 작동한다. 프린터 드라이버는 두가지 모두 둘다에서 작동한다.

Printing Process

인쇄 작업은 세가지 그룹의 단계로 나누어 진다:

. Client processes

. Spooler processes

. Printer processes

각 프로세스는 어떠한 작업을 수행하고 나서 다른 프로세스로 인쇄 작업을 전달한다. 예를 들어, 사용자가 어플리케이션에서 인쇄를 누르면 클라이언트 프로세스가 GDI를 호출함으로서 인쇄 작업을 생성하기 시작한다, 인쇄 작업 생성을 완료하고 나서 스풀러에게 인쇄작업을 전달한다. 스풀러는 인쇄 작업에서 어떠한 처리를 수행할 것이다 그리고 프린터 프로세서에게 전달할 것이다. 프린터 프로세스는 스풀러 프로세서에서 인쇄 작업을 받고 나서 프린터 언어를 비트맵으로 변환한 후에 프린트한다.

Client Processes

사용자는 어플리케이션으로부터 인쇄 작업을 전송한다. 어플리케이션은 Graphics Device Interface (GDI)를 호출한다. 프린트 출력물이 RAW 포맷으로 생성되면 GDI는 사용되지 않는다. GDI는 GDI가 프린터 언어로 작업을 생성해서 사용한다는 정보를 주기 위해 프린터 드라이버를 호출한다. GDI는 작업을 스풀러에게 전달한다.

Spooler Processes

. 스풀러(Winspool.drv)의 클라이언트 측은 서버 사이드 스풀러(Spoolsv.exe)에 대한 RPC 호출을 만든다.

. Spoolsv.exe는 프린터 라우터를 호출한다. (Spoolss.dll)

. 라우터(Spoolsv.dll)는 인쇄 작업을 Local Print Provide (LPP)로 전송하고 네트워크 프린터로 전달된 작업이면 리모트 프린터

서버로 전송한다.

. LPP는 인쇄 작업의 데이터 타입을 처리할 수 있는 것중의 하나를 찾기 위해 프린트 프로세서를 폴링한다.(정기적으로 조사)

. LPP는 적절하게 프린트하는데 필요한 작업을 수정하는 프린터 프로세서에게 작업을 전송한다.

. 프린트 프로세서는 페이지 구분자에게 작업을 전송한다. 필요하면 구분된 페이지가 추가된다.

. 작업은 적절한 포트 프린터 모니터로 전송된다. 프린터가 양방향성이면, 작업은 Printer Job Language(PJL) monitor와 같은 lan

guage monitor에게 전달되고 port 모니터로 전송된다. 작업이 단방향성이면, 작업은 포트 모니터로 직접적으로 전송된다.

Printer Processes

. 프린터는 프린터 스풀러로부터 인쇄 작업을 받는다.

. 프린터는 print language를 프린트할 비트맵으로 변환한다.

Printer Spooler Architecture

Introduction to Print Spooler : 프린터 스풀링은 사용자에 의해 설정된다. 작업은 스풀러에게 전송될 수 있다, 또는 프린터에게 직접 전송될 수도 있다. 작업이 스풀러에게 전송되면 가능하면 빨리 프린트를 시작하거나 스풀러에 전달된 마지막 페이지가 인쇄된 후에 프린트를 시작하도록 설정할 수 있다. 프린터에 작업을 직접 전달하면 전체 작업을 렌더링한 후에 프린터에 직접 전송한다. 프린트 작업을 스풀러에게 전달하면 여러분의 컴퓨터는 작업이 어떻게 처리되어야 하는지에 대한 메타-정보를 포함한 작업을 생성하고 스풀러에게 작업을 전송한다.

프린트 작업을 프린터에게 직접 전송하는 것은 좋다 왜냐하면 문서를 출력할 때의 잠재적인 실패 확률을 제거하기 때문이다, 그리고 모든 프린트 작업 렌더링이 여러분의 컴퓨터에서 끝나고, 콘트롤에 보다 노력을 기울이면 많은 사용자가 사용하고 있어서 프린터 서버의 큐가 밀려있을 때 처럼 다른 작업이 끝날때까지 기다릴 필요가 없다. 역으로 말하면, 여러분의 컴퓨터에서 프린트 작업을 렌더링하는것은 많은 자원을 소모하기 때문에 감소된 성능을 느끼거나 다른 작업이 끝날 때까지 프린트 작업을 기다려야 할 것이다.

프린트 작업을 스풀러에게 전송하는 것은 좋다 왜냐하면 여러분의 컴퓨터가 프린트 작업을 렌더할 필요가 없기 때문이다, 여러분의 컴퓨터 리소스가 보다 복잡하고 즉시 사용가능하다는 의미에서. 역으로 말하면, 스풀러를 가진 프린터 서버가 사용 불능상태이면 스풀러에 전송한 프린트 작업이 실패할 것이다, 여러분의 작업이 처리되기 전에 스풀링을 종료하기 위해 다른 작업을 기다려야 할 수도 있다.

프린트 인터페이스의 가장 중요한 컴포넌트는 프린트 스풀러이다. 프린트 스풀러는 프린트 작업을 관리하는 실행가능한 파일이다. 프린트의 관리는 정확한 프린터 드라이버의 위치 얻기, 드라이버 로딩, 프린트 작업으로 고수준의 함수 호출, 인쇄를 위한 프린트 작업 스케줄링, 등등을 수반한다. 스풀러는 시스템이 시작할 때 로드되고 OS가 종료될 때까지 실행을 계속한다. 인쇄하는 어플리케이션은 프린터 DC를 생성한다. 어플리케이션이 프린터 DC를 생성하면, 스풀러는 필요한 프린터 드라이버의 위치 결정과 같은 필요한 작업을 수행하고 적절한 프린터 드라이버를 로딩한다. 또한 프린트 작업을 기록하는데 사용되는 데이터 타입을 결정한다.

지원되는 데이터 타입은 EMF, ASCII text, raw data(PostScript와 PCL과 같은 모든 프린터의 데이터 타입) 추가적인 프린터 드라이버와 프린트 프로세서가 설치되면 custom data type이 스풀러에 추가될 수 있다. 프린트 작업은 출력물로 하나 이상의 페이지를 담을 수 있는 내부적으로 저장되는 문서이다 (지원되는 데이터 타입 중의 하나를 사용해서). 여러개의 형태로 구성된다; 예를 들어, 한장의 덧붙임장과 세개의 페이지로 구성된 총 4페이지로 구성될 수 있다. 프린트 작업은 StartDoc와 EndDoc 함수로 정의된다.(또는 묶일 수 있다.)

프린트 작업을 위한 기본 데이터 타입은 EMF이다. EMF 레코드는 텍스트 출력 명령어, raster graphics command, 등등을 저장하는데 사용되는 컴팩트한 구조이다. 어플리케이션이 StartDoc를 호출하면 스풀러는 스풀 파일과 데이터 파일을 생성하고 EMF 레코드를 스풀 파일로 저장하기 시작한다. 스풀과 데이터 파일은 OS 시스템 디렉토리에 생성된다. 스풀러는 EMF 레코드를 저장하기 위해서 스풀 파일을 사용한다, 폼, 프린터 작업의 데이터 타입, 대상 프린터와 같은 데이터를 기록하기 위해 데이터 파일을 사용한다. 스풀러는 작업이 성공적으로 프린트되면 이러한 파일들을 삭제한다.

MS Windows 프린터 스풀러는 다음과 같은 책임을 가지는 MS에서 제공하고 추가적으로 생산자가 제공하는 컴포넌트의 집합으로 구성된다:

. 프린트 작업이 로컬에서 처리되는 게 좋은지 네트워크를 통해서 처리되는게 좋은 지 결정한다.

. 특정한 타입의 프린터로 출력을 위해 프린터 드라이버와 함께 조합된 GDI로부터 생성되는 데이터 스트림 받아들이기.

. 데이터를 파일로 스풀링하기(스풀링이 가능하면)

. 논리 프린터 큐에서 처음으로 사용가능한 물리적 프린터 선택하기.

. 데이터 스트림을 스풀된 포맷(EMF와 같은)에서 프린터 하드웨어로 전송될 수 있는(PCL과 같은) 포맷으로 변환하기

. 데이트 스트림을 프린터 하드웨어로 전송하기

. 스풀러 컴포넌트와 프린터 폼을 위한 registry-based 데이터베이스 관리하기

윈도우즈 프린트 스풀러는 다음으로 구성되는 Directory Services를 지원한다:

. 프린트 큐 publishing

. 세개의 레지스트리 키 관리하기

. Allowing access to spooler-maintained registry keys.

. Returning a print queue's publication state

Spooler Components

Microsoft Windows 스풀러의 중요한 컴포넌트는 다음의 다이어그램으로 나타낼 수 있다. 프린트 스풀러는 프린트 라우터, 로컬과 원격 프린트 프로바이더, 프린트 프로세서, language와 port 모니터를 포함한 컴포넌트의 그룹으로 구성된다.

. Application : 프린트 어플리케이션은 GDI 함수를 호출함으로서 인쇄 작업을 생성한다.

. GDI : GDI는 사용자 모드와 커널 모드 컴포넌트를 둘다 가지고 있다. 사용자 모든 컴포넌트 Win32 GDI는 그래픽 지원이 필요한

Win32 어플리케이션에서 사용된다. 커널 모드 컴포넌트 그래픽 엔진(또는 그래픽 렌더링 엔진) 은 그래픽 디바이스 드라이버가

사용할 수 있는 서비스와 함수를 export한다.

. Spoolsv.exe: Spoolsv.exe는 스풀러의 API 서버이다. 스풀러의 Win32 API를 구성하는 함수를 export하고 서버에 접속하기 위한

RPC stubs를 제공한다. 이 모듈은 RPC 인터페이스를 스풀러 Win32 API의 서버 측에 export한다. spoolsv.exe의 클라이언트는

winspool.drv(locally)와 Win32spl.dll(remotely)를 포함하고 있다. API 함수들을 구현하지만 대부분의 함수 호출은 라우터(spool

ss.dll)의 수단으로서 프린트 프로바이더에게 전달된다.

. Router: spoolss.dll 라우터는 어떤 프린트 프로바이더를 호출할지 결정한다, 프린터의 이름 또는 각 함수 호출과 함께 제공되는

핸들을 기반으로하여, 함수 호출을 정확한 프로바이더에게 전달한다.

. Print Provider : 특정한 프린트 디바이스를 지원하는 프린트 프로바이더

. Print Monitor : 윈도우즈 XP는 두가지 형태의 프린트 모니터를 지원한다: language 모니터와 포트 모니터

프린터 하드웨어가 어플리케이션이 실행중인 시스템에 로컬이면, "client"와 "server"는 동일한 시스템이다(비록 다이어그램에서 명확하지 않더라도)

Note : 모든 스풀러 컴포넌트는 사용자 모드에서 실행된다.

Print Providers

이번 섹션은 다음의 토픽을 제공한다 :

Introduction to Print Providers

프린트 프로바이더는 인쇄 작업을 로컬 또는 리모트 프린트 디바이스로 지시하는 책임이있다. 또한 서버의 프린트 큐를 시작하고 멈추고 열거하는 것과 같은 프린트 큐 관리 작업에 대한 책임이 있다. 프린트 프로바이더는 고수준의 기계 독립적인, 프린터 서버의 OS 독립적인 뷰를 정의한다. 모든 프린트 프로바이더는 프린트 프로바이더 기능의 공통적인 부분을 구현한다. 이런 기능은 스풀러의 라우터(spoolss.dll)에 의해 호출되는 API 함수들의 집합으로 정의된다.

Print Provider Flow Paths

다이어그램을 볼때, 여러분의 다음의 것들을 고려하는 게 좋다:

. 프린터가 클라이언트 시스템에 의해 관리되면, 인쇄 작업은 로컬 프린트 프로바이더(localspl.dll)에 의해 처리된다. localspl.dll

에 의해 관리되는 프린터는 클라이언트에 물리적으로 로컬일 필요는 없다; 네트워크 카드를 통해서 직접적으로 연결될 수 있다.

. 프린터가 NT 기반의 OS 시스템 서버에 위치하고 있다면, 네트워크 프로바이더(win32spl.dll)는 클라이언트의 라우터로부터 서버

의 spoolsv.exe 프로세스로 호출을 전달하기 위해 RPC를 사용한다.

. 프린터가 서버의 다른 타입으로 위치하고 있다면, 로컬 프린트 프로바이더 서버 타입을 지원하는 또는 네트워크 프린트 프로바이

더에 의해 접속될 수 있다, 서버에 의해 지원되는 네트워크 프로토콜과 데이터 포맷을 사용해서.

. 로컬 프린트 프로바이더가 리모트 프린터로 접속하기 위해서는 리모트 프린터 또는 서버에 의해 식별되는 네트워크 프로토콜을

사용할 수 있는 포트 모니터를 담고 있어야 한다.

Print Provider Capabilities

미리 정의된 API 함수들을 지원함으로서 Windows 프린트 프로바이더는 다음의 기능을 제공할 수 있다 :

. Print Queue Management: 프린트 큐를 위한 파라미터를 추가하고, 지우고, 열고, 닫고, 열거하고, 설정한다. 또한, 프린트 큐의

상태 변화를 통지한다.

. Printer Driver Management: 프린트 드라이버를 위한 디렉토리를 추가하고, 지우고, 열거하고, 명세한다.

. Print Job Creation : 문서를 시작하고 끝낸다, 문서 페이지를 시작하고 끝낸다, 작업의 데이터 스트림을 포트로 쓴다, 프린터의

상태 정보를 읽느다.

. Print Job Scheduling : 인쇄 작업을 위한 파라미터의 스케줄링, 열거, 설정

. Form Management:

. Print Processor Managament:

. Print Monitor Management:

. Port Management:

. Registry Management:

. Other Capabilities:

이런 기능은 프린트 프로바이더에 의해 정의되는 기능의 집합으로 구현된다. 프린트 프로바이더를 정의하기 위해 지원되는 많은 함수들이 있다. 함수들은 다음의 그룹으로 나누어 진다 :

. Initialization Functions

. Print Queue Management Functions

. Printer Driver Management Functions

. Print Job Creation Functions

. Print Job Scheduling Functions

. Forms Management Functions

. Print Processor Management Functions

. Print Monitor Management Functions

. Port Management Functions

. Registry Management Functions

. Other Functions

Local Print Provider

윈도우를 위한 로컬 프린트 프로바이더는 잡 콘트롤과 로컬 프린트 프로바이더의 포트 모니터를 통해서 접속되는 모든 프린터를 위한 프린터 관리 기능을 제공한다. (클라이언트 administraotror는 Add Printer Wizard을 사용할 때 Local Printer 옵션을 선택함으로서 프린터와 같은 것에 대한 접속을 설정한다) 그러한 프린터는 로컬 시스템의 시리얼과 패러럴 포트에 대한 연결을 포함하고 있다. 또한 스카시 포트와 같은 다른 I/O 채널에 연결되는 디바이스를 포함할 수 있다, 리모트의 non-NT-based OS 서버에 연결된 프린트를 통해서.

Control Flow in Local Printer Provider

다이어그램이 보여주는 것처럼, 어플리케이션은 GDI를 호출함으로서 인쇄 작업을 생성한다. 인쇄 작업의 초기 출력 포맷이 EMF인지의 여부와는 상관없이 로컬 프린터 프로바이더의 작업 생성 API는 스풀 파일을 생성한다. 나중에 작업이 스케줄되면, 스풀 파일이 읽히고 포맷이 EMF이면 EMF 프린트 프로세스는 RAW 포맷의 변환을 다시 GDI로 되돌려서 전송한다, 프린터의 그래픽 DLL의 도움을 받아서. 변환된 데이터 스트림은 프린터에게 (re-spooled 없이) 로컬 프린트 프로바이더를 통해서 다시 전송될 수 있다.

Printer Driver

프린터 드라이버는 사용되는 프린터에 종속적인 정보를 담을 수 있다. 프린터 드라이버는 사용자의 컴퓨터에 위치하고 있고 인쇄 작업을 렌더하기 위해서 GDI에 의해 사용된다. 프린터 드라이버는 프린터와 플로터와 어떻게 정보를 주고 받는지를 이해하는 소프트웨어 프로그램이다. 다른 하드웨어와 OS를 지원하기 위해서 프린트 서버에 다양한 드라이버가 설치되어야 한다. 예를 들어, 윈도우 95와 윈도우 98을 사용하고 있는 클라이언트와 프린터를 공유하는 윈도우 2000 서버에서 작동하는 서버는 적절한 드라이버를 설치하기를 원할 것이다 그래서 사용자는 드라이버를 잘못 설치했다는 메시지를 원하지 않을 것이다. 프린터 드라이버는 문서의 각 글자를 생성하기 위해 필요한 스펙을 포함하는 프린터-설정 정보를 GDI에 전송한다. 또한 프린트를 정확하게 하는 필요한 helper 서비스 또는 유틸리티를 전송할 것이다.

프린터 드라이버는 세가지 구분된 파일로 구성된다:

1. 프린터 그래픽 드라이버(예를 들어, PSCRIPT.DLL, RASDD.DLL 또는 PLOTTER.DLL). 그래픽 드라이버는 프린트 렌더링에 대한 책임이 있다. (그래픽 엔진으로 부터 프린트 렌더링 명령어를 프린터가 이해할 수 있는 프린터 명령어로 변환하는) 각 그래픽 드라이버는 다른 프린터 언어를 처리한다. 예를 들어 :

. PSCRIPT.DLL : PostScript 프린터 언어를 다룬다.

. PLOTTER.DLL : 많은 플로터가 사용하는 HPGL/2 언어를 다룬다.

. RASDD.DLL : 래스터(비트맵) 이미지에 기반으로 하는 프린터 언어를 다룬다, PCL과 대부분의 도트 매트릭스 프린터 언어를

포함하는.

2. 프린터 인터페이스 드라이버(예를 들어, PSCTPTUI.DLL, RASDDUI.DLL 또는 PLOTUI.DLL). 이러한 DLL은 여러분이 프린터 관

리자에서 프린터를 설정할 때 볼 수 있는 UI를 가지고 있다. 라우터의 클라이언트 측에 의해 호출된다. (WINSPOOL.DRV)

3. Characterization files : characterization 데이터 파일은 프린트 디바이스에 대한 모델 종속적인 정보를 제공한다.

Printer Driver Components

모든 윈도우즈 프린터 드라이버는 다음의 컴포넌트로 구성된다:

. 프린터 그래픽 DLL은 인쇄 작업을 렌더링하는 GDI를 도와준다, 렌더된 데이터 스트림을 프린터 스풀러로 전송한다.

. 프린터 인터페이스 DLL은 드라이버의 설정 파라미터에 대한 UI와 프린터와 관련된 시스템 이벤트를 드라이버가 알아차릴 수 있

기 위해서 스풀러가 호출하는 인터페이스 둘다를 제공한다.

Print Processors

프린트 프로세서는 프린터 드라이버를 호출하는 DLL 이다. 어플리케이션은 여러분의 컴퓨터에 설치되지 않는 프린트 프로세서를 사용하도록 시도한다. 스풀러는 작업을 언제 인쇄할지를 결졍하기 위해 현재의 프린트 작업과 대상 프린터를 모니터한다. 스풀러가 작업을 인쇄하기로 결정하면 프린터 프로세서를 호출한다. 프린트 프로세서는 하드 디스크로부터 스풀된 프린트 작업을 이동하기 위해서 프린터 드라이버와 함께 작동한다.

Introduction to Print Processors

프린트 프로세서는 프린트 작업의 스풀된 데이터를 프린터 모니터로 전송될 수 있는 포맷으로 변환할 책임이 있다. 또한 인쇄 작업을 일시 정지, 다시 시작, 취소하는 어플리케이션 요청을 처리할 책임이 있다.

인쇄 작업의 스풀된 데이터는 스풀 파일에 담겨 있다. 프린터 프로세서는 파일을 읽고 데이터 스트림으로의 변환 작업을 수행하고 변환된 데이터를 스풀러 쓴다. 스풀러는 데이터 스트림을 적절한 프린터 모니터로 전송한다.

MS 윈도우즈 2000 이후의 버전은 다음의 테이블에 나타난 프린트 프로세서를 가지고 있다.

Print Processor Input Data Types Output Data Types

localspl.dll* EMF

RAW RAW

TEXT

sfmpsprt.dll PSCRIPT1 RAW

* 윈도우즈 2000 부터 localmon.dll 과 winprint.dll은 localspl.dll에 포함되어 있다.

데이터 타입에 대한 자세한 정보는 다음을 보라:

. EMF Data Type

. RAW Data Type

. TEXT Data Type

. PSCRIPT1 Data Type

EMF Data Type

RAW Data Type

Difference Between EMF and RAW Data Formats?

TEXT Data Type

Processing a Print Job

스풀러가 인쇄 작업을 프린트 프로세서에 전송할 준비가 되면 프린트 프로세서의 OpenPrintProcessor 함수를 호출한다. 이 함수는 초기화 작업을 수행하고 핸들을 리턴한다. 스풀러는 PrintDocumentOnPrintProcessor를 호출할 수 있다, 입력 포맷의 데이터 스트림을 출력 포맷으로 변환하고 변환된 스트림을 스풀러에게 리턴하는 프린트 프로세스 함수인. 입력 포맷이 NT-based-operating system EMF이면 PrintDocumentOnPrintProcessor 함수는 Using GDI Functions in Print Processor에 있는 함수를 사용해서 EMF 레코드의 재생을 제어할 수 있다. 이런 함수는 프린트 프로세서와 프린터 드라이버 간의 인터페이스를 제공한다. 이러한 인터페이스는 프린터 페이지의 물리적인 레이아웃을 통제할 수 있는 프린트 프로세서를 허용한다 따라서 하나의 물리적인 페이지에 여러개의 문서를 출력("N-up" 프린팅)하고 페이지의 역순으로 출력하고 각 페이지를 여러장 출력하는 것과 같은 편리한 기능을 구현할 수 있다.

프린터 프로세서의 출력 데이터 스트림은 스풀러에게 리턴되어야 한다. 전형적으로, 데이터 변환이 프린터 드라이버의 프린터 그래픽 DLL (EMF 입력 데이터을 위한 경우처럼)과 상호작동할 필요가 있다면, 그래픽 DLL은 EngWriterPrinter를 호출함으로서 스풀러에게 스트림을 리턴한다. 그렇지 않으면, 변환이 프린터 그래픽 DLL(RAW 입력 데이터의 경우 처럼)을 호출하지 않으면 프린트 프로세서는 WritePrinter를 호출한다. PrintDocumentOnPrintProcessor 함수는 스풀러가 프린터 프로세서의 ControlPrintProcessor 함수를 비동기적으로 호춤함으로서 인터럽트될 수 있다. 이 함수는 인쇄 작업을 멈추고, 다시 시작하고, 취소할 수 있는 어플리케이션의 능력을 구현한다. PrintDocumentOnPrintProcessor이 데이터 스트림을 변환하고 리턴한 다음에 스풀러는 프린트 프로세서의 ClosePrintProcessor 함수를 호출한다.

Installing a Print Processor

프린트 프로세서를 설치하기 위해서, 설치 어플리케이션은 스풀러의 AddprintProcessor 함수를 호출해야 한다. 프린트 큐와 프린트 프로세서를 연결하기 위해서는 PrintProcessor 엔트피의 INF 파일에 파일 이름을 입력하라. 이 entry는 어떠한 프린트 프로세서에 연결되는 모든 프린트 큐를 포함하고 있어야만 한다. 보다 자세한 정보는, Printer INF 파일을 보라. 설치 어플리케이션이 스풀러의 AddPrinter 함수를 호출하면, 입력 매개변수로 PRINTER_INFO_2 구조체를 사용해서, 구조체의 멤버로 프린트 프로세서 이름(INF 파일에서 얻을 수 있는)을 명세한다.

Associating a Print Processor with a Pnp-installed Print Queue

PnP 관리자가 윈도우즈 2000 또는 윈도우즈 XP에서 작동하고 있는 시스템의 프린트 큐를 찾고 설치하면 그리고 기본 윈도우즈 프린트 프로세서인 WinPrint 가 아닌 PrintProcessor 엔트리를 담고 있는 프린트 큐를 설치하기 위해 INF 파일이 사용되었다면, 프린트 프로세서는 프린트 큐에 연결되지 않을 것이다. 하지만 프린트 프로세서는 설치될 것이다. (여러분이 프린터 추가하기 마법사를 이용해서 프린트 큐를 설치했다면 프린트 프로세서가 프린트 큐에 정확하게 연결되었다는 것을 기억하라. 또한 Windows Server 2003 이후의 버전의 PnP 매니저는 프린트 프로세서와 프린트 큐를 정확하게 연결한다는 것을 기억하라.)

Windows 2000과 Windows XP에서 Plug and Play 인스톨을 위한 프린트 큐와 프린트 프로세서를 연결하기 위해서는 프린터 인터페이스 DLL의 DrvPrinterEvent 함수에 PRINTER_EVENT_INITIALIZE case를 추가하라. MS 윈도우즈 서버 2003 이후 버전에서는 DrvPrinterEvent 함수에 PRINTER_EVENT_INITAILIZE case를 추가할 필요가 없다.

Print Monitor

프린터 모니터는 프린트 스풀러의 프린트 데이터 스트림을 적절한 포트 드라이버로 전달할 책임이 있다. 정의된 두가지 형태의 프린트 모니터는 language 모니터와 포트 모니터이다.

Language Monitor

language 모니터는 두가지 목적을 제공하는 사용자 모드 DLLs 이다:

. 소프트웨어가 접근 가능한 상태 정보를 제공하는 능력이 있는 프린트 스풀러와 양방향 프린터간의 양방향 커뮤니케이션 경로를

제공한다.

. 데이터 스트림에 프린터 작업 언어로 정의된 명령어와 같은 프린터 제어 정보를 추가한다.

MS는 PJL을 지원하는 pjlmon.dll language 모니터를 제공하고 PJL 프린터를 위한 양방향 커뮤니케이션을 제공한다. 이 모니터는 샘플 language 모니터로서 DDK에 포함되어 있다.

customized language 모니터는 단방향 또는 양방향 프린터를 위한 다른 작업 콘트롤 language를 지원하기 위해 작성될 수 있다.

language 모니터는 선택적이고 Installing a Print Monitor에 기술된 것 처럼 프린터의 INF 파일에 포함되어 있다면 특정한 프린터 타입에만 연결된다.

language 모니터가 프린터에 연결되면 language 모니터는 프린트 프로세서로부터 프린터의 데이터 스트림을 받고 수정하고 프린터의 포트 모니터로 그것을 전달한다.

Port Monitor

포트 모니터는 사용자 모드 DLLs로 구성된다. 사용자 모드 프린트 스풀러와 I/O 포트 하드웨어에 접속하는 커널 모드 포트 드라이버간의 커뮤니케이션 경로를 제공할 책임이 있다. 포트 모니터는 Platform SDK documentation에 기술되어 있는 것처럼 전형적으로 CreateFile, WriterFile, ReadFile, DeviceIOControl 함수를 사용한다 커널 모드 포트 드라이버와 커뮤니케이트하기 위해서. 포트 모니터는 또한 Managing a Port에 기술된 것처럼 서버의 프린터 포트의 설정과 관리를 위한 책임이 있다.

NT-based-OS 사용자의 "printer"의 관점은 실제 프린트 큐이다, 연결될 수 있는 하나 이상의 프린터 디바이스에 대한. 포트는 프린트 큐와 단일 프린트 디바이스 간의 물리적인 연결이다. 각 포트 모니터는 하나 이상 타입의 포트의 하나 이상의 인스턴스를 지원한다. 예들 들어, localmon.dll 샘플 포트 모니터는 모든 서버의 로컬 COM과 LPT 포트를 지원할 수 있다. (프린터 폴더는 Platform SDK documentation의 AddPrinter 함수를 호출함으로서 포트 모니터에 포트를 할당한다.)

여러개의 프린트 디바이스(여러개의 포트를 통해서)를 나타내는 프린트 큐를 위해서, 스풀러는 각 인쇄 작업을 첫번째 가능한 포트에 전송한다. 포트 모니터가 특정한 포트가 바쁘거나 에러를 만났다고 알려주면, 스풀러는 큐에 작업을 재전송하고 포트 모니터에 의해 지원되는 다른 포트를 명세한다.

게다가 윈도우즈 2000 이후 OS는 여러개의 추가적인 포트 모니터를 제공한다. 윈도우즈 2000 Server Resource Kit는 이러한 포트 모니터 각각을 기술한다. customized 포트 모니터는 추가적인 형태의 I/O 포트 하드웨어를 지원하다록 작성될 수 있다.

윈도우즈 2000 이후의 버전에 각 포트 모니터는 두개의 DLL로 나누어 진다:

. Port Monitor UI DLL: 포트 모니터의 UI DLL은 UI 기능을 담고 있고 프린트 클라이언트 시스템에서 실행된다. 클라이언트 시스템

의 System32 서브 디렉토리에 존재해야 한다.

. Port Monitor Server DLL: 포트 모니터의 서버 DLL은 포트 통신 기능을 가지고 있고 프린트 서버에서 실행된다. UI를 표시해서는

안된다.

Initializing a Print Monitor

스풀러가 프린터 모니터 DLL을 로드하기 위해 LoadLibrary를 호출하면 시스템은 즉시 DLL의 DllEntryPoint 함수를 호출한다. Platform SDK 문서에 기술된 DisableThreadLibraryCalls를 호출하는 entry point 함수는 일반적으로 좋은 생각이다, 그래서 DLL은 스레드가 생성되고 제거될때 통지될 필요가 없다.

각 DLL은 초기화 함수를 export한다, LoadLibrary를 호출한후에 스풀러를 호출하는. Language 모니터 DLL과 포트 모니터 서버 DLLs은 InitailizePrintMonitor2 함수를 export한다. 포트 모니터 UI DLLs은 InitializePrintMonitorUI 함수를 export한다.

이런 두가지 초기화 함수는 프린트 모니터에 의해 정의된 함수의 나머지에 대한 포인터를 리턴할 책임이 있다, 그래서 스풀러는 그들을 호출할 수 있다. 초기화 함수는 또한 load-time 초기화 작업을 수행할 수 있다. 모니터의 InitializePrintMonitor2 함수는 모니터 인스턴스 핸들을 리턴한다. 모니터는 instance-specific 정보를 저장하기 위해서 로컬 메모리를 할당하는 것이 좋다, 그리고 할당된 메모리에 대한 식별자로서 모니터 핸들을 사용한다.

스풀러가 처음 시작되면, 설치된 모든 모니터 DLL을 로드한다. 모든 모니터 초기화 함수를 호출한 후에, 스풀러는 모니터에 의해 지원되는 포트를 열거하는 각 포트 모니터의 EnumPorts 함수를 호출한다. (Adding a Port에 기술된 것 처럼 모니터의 데이터베이스에 포트가 추가되었다면 모니터는 포트를 지원한다). 그러면 지원되는 포트가 열린다, Opening and Closing a Port에 기술된 것 처럼.

Opening and Closing a Port

Adding a Port에 기술된 것처럼 포트가 추가된 후에 스풀러는 적절한 language 모니터의 OpenPortEx 함수를 호출함으로서 포트를 열수 있다.

language 모니터는 포트 핸들을 생성하고 리턴하기 위해서 OpenPortEx 함수를 사용한다. 전형적으로, language 모니터는 연결된 포트 모니터의 OpenPort 함수를 호출하고 language 모니터는 단지 포트 모니터의 OpenPort로 부터 얻은 핸들을 리턴한다.

language 모니터가 포트에 연결되지 않으면 스풀러는 포트 모니터의 OpenPort 함수를 직접적으로 호출한다.

스풀러는 포트로 통하는 경로를 한번에 하나밖에 허용하지 않는다. 따라서, 특정한 모니터에서 OpenPortEx(또는 OpenPort) 를 호출한 후에 포트가 닫히기 전에 동일한 포트를 열려는 시도를 하지 않는다.

포트가 열리고 나면 스풀러는 작업을 인쇄하기 위한 추가 적인 함수를 호출할 수 있다, Priting a Print Job에서 기술된 것처럼, 입력 매개변수로 포트 핸드를 사용해서. 모니터는 그렇게 작성되는 것이 좋다, 포트가 열리고 난후에 스풀러는 포트를 닫기 전에 여러개의 인쇄 작업을 전송할 수 있다.

작업이 다른 language 모니터를 통해서 전송되어야 한다면, 프린트 큐가 포트에 연결되어 있지 않거나 스스템이 꺼졌을 때 스풀러는 포트를 닫는다. 포트를 닫기 위해서 스풀러는 language 모니터의 ClosePort 함수를 호출한다. 이 함수는 포트가 열렸을 때 생성된 핸들을 무효화한다.

language 모니터가 포트에 연결되어 있지 않으면, 스풀러는 포트 모니터의 ClosePort 함수를 직접적으로 호출한다.

Printing a Print Job

포트가 열리고 나면 Opening and Closing a Port에서 기술한 것 처럼, 스풀러는 인쇄 작업을 포트로 전송할 수 있다.

각 인쇄 작업은 language 모니터와 포트 모니터의 StartDocPort와 EndDocPort 함수 호출을 하는 스풀러에 의해 delimte된다. 스풀러는 프린트 프로세서가 스풀러의 StartDocPrinter와 EndDocPrinter 함수를 호출할 때 이러한 함수를 호출한다, 이것은 Platfomr SDK documentation에 기술되어 있다. StartDocPort와 EndDocPort 함수의 영역 내에서 모니터의 WritePort, ReadPort, GetPrinterDataFromPort 함수에 대한 unlimited 스풀러의 호출이 발생할 수 있다.

이런 함수들 각각은 입력 매개변수로 명세된 OpenPortEx(또는 OpenPort)에 의해 리턴되는 포트 핸들을 필요로한다. 전형적으로, language 모니터는 연결된 포트 모니터에서 like-named 함수를 호출함으로서 각 함수를 구현한다.

스풀러가 데이터 스트림을 포트에 전송하기 위해서 language 모니터의 WritePort 함수를 호출할때, 함수는 일반적으로 PJL 명령어 같은 language-specific 정보를 추가한다, 연결된 포트 모니터의 WritePort 함수로 전달하기 전에 데이터 스트림을 수신하기 위해서.

ReadPort 함수는 양방향 프린터 하드웨어로부터 상태 정보를 얻기 위해서 사용된다, Platform SDK documentation에 기술된 것처럼 language 모니터는 SetPort를 호출함으로서 스풀러에 전송한다.

프린트 하드웨어가 양뱡향이면, language 모니터와 포트 모니터 둘다는 GetPrinterDataFromPort 함수를 지원하는 것이 좋다. language 모니터의 GetPrinterDataFromPort 함수는 입력으로 레지스트리 값을 얻고 이름을 위한 값을 얻는(일반적으로, 연결된 포트 모니터의 WriteProt 와 ReadPort 함수를 호출함으로서) 것이 좋다, 그리고 호출자에게 값을 리턴한다. 포트 모니터의 GetPrinterDataFromPort 함수는 입력으로 I/O 콘트롤 코드를 받는 것이 좋다, 포트 드라이버에 콘트롤 코드를 전달하기 위해서 DeviceIoControl(Platform SDK documentation에 기술된 것처럼)을 호출하고 결과를 리턴한다.

Initializing a Print Monitor

이번 섹션은 프린터 모니터를 설치하기 위해 사용되는 방법을 기술한다. (프린터를 설치할 때 사용한 동일한 INF 파일을 사용해서 프린터 모니터를 설치할 수 있다. INF 파일에 대한 자세한 정보는 Plug and Play and Power Management 를 보라.)

Insalling a Language Monitor: language 모니터를 설치하기 위해서 LanguageMonitor 엔트리를 사용해서 INF 파일에 있는 파일 이름을 리스트해야한다. 이 엔트리는 language 모니터를 사용하는데 필요한 프린터를 제어하는 모든 프린터 드라이버에 포함되어야만 한다. 자세한 정보는 Printer INF Files를 보라. Add Driver 마법사 또는 Add Printer 마법사는 INF 파일을 일고 프린터 드라이버에 연결된 langauge 모니터를 설치한다. 대안으로는 custom 설치 어플리케이션이 스풀러의 AddMonitor 함수를 호출함으로서 language 모니터를 설치할 수 있다, 특정한 모니터 DLL에만 명시적으로 설치하기 위해서.

Installing a Port Monitor: 포트 모니터를 설치하기 위해서, 여러분의 installation medium은 PortMonitors 섹션을 담고 있는 프린터 INF 파일(that is, an INF file for which Class = Printer)을 담고 있어야 한다. 이번 섹션의 단일 entry는 두개의 엔트리를 담고 있는 install section을 가르킨다: 포트 모니터를 구성하는 모든 파일을 리스트하는 INF CopyFiles directive, and a PortMonitorDll entry that specifies which DLL in the previous list implements the port monitor interface. 다음의 예제 코드는 이러한 관점을 보여준다. PortMonitors 섹션은 SamplePortMon이라는 install section을 가르킨다. 이 section에서, an INF CopyFiles directive copies three files that make up the port monitor. 다음의 PortMonitorDll entry는 포트 모니터 인터페이스를 구현하는 DLL을 식별한다.

[PortMonitors]

"Sample Port Monitor" = SamplePortMon

[SamplePortMon]

CopyFiles = @file1.dll, @file2.dll, @file3.hlp

PortMonitorDll = file1.dll

포트 모니터를 설치하기 위해서, 제어판의 Printers 폴터를 열어라. Printers 폴더의 File 메뉴에서 Server 프로퍼티를 선택하라. File Server Properties 대화상자에서 Ports 탭을 클릭하고 Add Prot 버튼을 클릭하라. Printer Ports 대화상자에서, New Port Type 버튼을 클릭하라. 텍스트 입력 상자에서 INF 파일에 대한 경로를 입력하고 OK를 클릭하라.

다른 방법으로는 custion 설치 어플리케이션은 AddMonitor 함수를 호출함으로서 포트 모니터 DLL을 설치할 수 있다.

Bidirectional Communication

스풀러는 어플리케이션 또는 드라이버와 프린터 간의 Bidi 커뮤니케이션에 대한 지원을 제공한다. 이러한 지원은 어플리케이션 또는 드라이버가 하나이상의 요청을 프린터에게 전송할 수 있도록 한다, 그리고 프린터가 이러한 요청에 응답할 수 있도록 한다.

Bidirectional Support Architecture

bidi 커뮤니케이션은 두가지 부분을 지원한다: bidi 커뮤니케이션 스키마와 bidi 스풀러 API. 스키마는 디바이스와 요청을 위한 포맷을 만들 수 있는 어플리케이션의 요청을 기술한다. 스풀러 API는 요청을 디바이스에 전달하고 또한 bidi 데이터를 전송하고 수신할 수 있다. 어플리케이션은 또한 네트워크 프린터를 위한 네트워크 프린트 프로바이더 또는 리모트 프린터 서버에 연결된 프린터에 요청을 전달할 수 있다.

프린터에게 단일 요청을 전달하기 위해서는 어플리케이션 또는 프린터는 처음에 요청을 구성해야만 한다, 그리고 IBidiSpl::SendRecv 메소드를 호출한다. 여러개의 요청을 전달하기 위해서는 어플리케이션 또는 드라이버는 요청들의 리스트를 구성하고 IBidiSpl::MultiSendRecv 메소드를 호출한다. 요청을 수신한 후에, 스풀러의 클라이언트측(winspool.drv)에서 서버측 스풀러에게 전달 한다.(spoolsv.exe). 서버측 스풀러는 로컬 컴퓨터에 있을 수 있고 또는 리모트의 네트워크 프린트 서버에 있을 수 있다. 서버측 스풀러가 요청을 수신하면, 데이터를 파싱한다. 서버측 스풀러는 어플리케이션 또는 서버에 의해서 사용하기 적절한 형태로 데이터를 변환한다, 그리고 다시 클라이언트 측 스풀러에게 돌려준다, 마지막으로 요청을 보낸 쪽으로 돌려보낸다.

[출처] Printing Architecture|작성자 네이밍