vmware-vdiskmanager.exe

- vmware 설치시 포함되어 있는 커맨드 라인 유틸리티로,

가상 하드디스크 생성
가상 하드디스크의 단편화 제거 (조각 모음..)
shrink(오그라들다?..이건 잘-_-...가상 하드를 압축한다는 이야기인지..)
가상 하드디스크 타입의 변경(고정 크기와 가변 크기)
가상 하드디스크 용량 증가 (maximum size 를 증가시킴. 감소는 않되는 듯-)

등의 기능을 지원한다.


가상 하드디스크 Maximum Size 변경하기

  vmware-vdiskmanager -x <new-capacity> <disk-name>

<new-capacity> 의 단위는 Kb, Mb, Gb 를 사용하며, 입력한 capacity 가 가상 하드디스크의 Maximum Size 가 된다.

ex) vmware-vdiskmanager.exe -x 36Gb myDisk.vmdk



- 가상 하드디스크의 크기를 16Gb 로 변경하는 중.




이제 윈도 2003 서버에 비스타를 업그레이드 시켜 봅시다...;;;;


더 자세한 사항은 이곳으로..

[http://www.vmware.com/support/ws45/doc/disks_vdiskmanager_run_ws.html#1057509]

How do Windows NT System Calls REALLY work?


Most texts that describe Windows NT system calls keep many of the important details in the dark. This leads to confusion when trying to understand exactly what is going on when a user-mode application "calls into" kernel mode. The following article will shed light on the exact mechanism that Windows NT uses when switching to kernel-mode to execute a system service. The description is for an x86 compatible CPU running in protected mode. Other platforms supported by Windows NT will have a similar mechanism for switching to kernel-mode.

By John Gulbrandsen 8/19/2004
John.Gulbrandsen@SummitSoftConsulting.com

What is kernel-mode?

Contrary to what most developers believe (even kernel-mode developers) there is no mode of the x86 CPU called "Kernel-mode". Other CPUs such as the Motorola 68000 has two processor modes "built into" the CPU, i.e. it has a flag in a status register that tells the CPU if it is currently executing in user-mode or supervisor-mode. Intel x86 CPUs do not have such a flag. Instead, it is the privilege level of the code segment that is currently executing that determines the privilege level of the executing program. Each code segment in an application that runs in protected mode on an x86 CPU is described by an 8 byte data structure called a Segment Descriptor. A segment descriptor contains (among other information) the start address of the code segment that is described by the descriptor, the length of the code segment and the privilege level that the code in the code segment will execute at. Code that executes in a code segment with a privilege level of 3 is said to run in user mode and code that executes in a code segment with a privilege level of 0 is said to execute in kernel mode. In other words, kernel-mode (privilege level 0) and user-mode (privilege level 3) are attributes of the code and not of the CPU. Intel calls privilege level 0 "Ring 0" and privilege level 3 "Ring 3". There are two more privilege levels in the x86 CPU that are not used by Windows NT (ring 1 and 2). The reason privilege levels 1 and 2 are not used is because Windows NT was designed to run on several other hardware platforms that may or may not have four privilege levels like the Intel x86 CPU.

The x86 CPU will not allow code that is running at a lower privilege level (numerically higher) to call into code that is running at a higher privilege level (numerically lower). If this is attempted a general protection (GP) exception is automatically generated by the CPU. A general protection exception handler in the operating system will be called and the appropriate action can be taken (warn the user, terminate the application etc). Note that all memory protection discussed above, including the privilege levels, are features of the x86 CPU and not of Windows NT. Without the support from the CPU Windows NT cannot implement memory protection like described above.

Where do the Segment Descriptors reside?

Since each code segment that exists in the system is described by a segment descriptor and since there are potentially many, many code segments in a system (each program may have many) the segment descriptors must be stored somewhere so that the CPU can read them in order to accept or deny access to a program that wishes to execute code in a segment. Intel did not choose to store all this information on the CPU chip itself but instead in the main memory. There are two tables in main memory that store segment descriptors; the Global Descriptor Table (GDT) and the Local Descriptor Table (LDT). There are also two registers in the CPU that holds the addresses to and sizes of these descriptor tables so that the CPU can find the segment descriptors. These registers are the Global Descriptor Table Register (GDTR) and the Local Descriptor Table Register (LDTR). It is the operating system''s responsibility to set up these descriptor tables and to load the GDTR and LDTR registers with the addresses of the GDT and LDT respectively. This has to be done very early in the boot process, even before the CPU is switched into protected mode, because without the descriptor tables no memory segments can be accessed in protected mode. Figure 1 below illustrates the relationship between the GDTR, LDTR, GDT and the LDT.

Since there are two segment descriptor tables it is not enough to use an index to uniquely select a segment descriptor. A bit that identifies in which of the two tables the segment descriptor resides is necessary. The index combined with the table indicator bit is called a segment selector. The segment selector format is displayed below.

As can be seen in figure 2 above, the segment selector also contains a two-bit field called a Requestor Privilege Level (RPL). These bits are used to determine if a certain piece of code can access the code segment descriptor that the selector points to. For instance, if a piece of code that runs at privilege level 3 (user mode) tries to make a jump or call code in the code segment that is described by the code segment descriptor that the selector points to and the RPL in the selector indicates that only code that runs at privilege level 0 can read the code segment a general protection exception occurs. This is the way the x86 CPU can make sure that no ring 3 (user mode) code can get access to ring 0 (kernel-mode) code. In fact, the truth is slightly more complicated than this. For the information-eager please see the further reading list, "Protected Mode Software Architecture" for the details of the RPL field. For our purposes it is enough to know that the RPL field is used for privilege checks of the code trying to use the segment selector to read a segment descriptor.

Interrupt gates

So if application code running in user-mode (at privilege level 3) cannot call code running in kernel-mode (at privilege level 0) how do system calls in Windows NT work? The answer again is that they use features of the CPU. In order to control transitions between code executing at different privilege levels, Windows NT uses a feature of the x86 CPU called an interrupt gate. In order to understand interrupt gates we must first understand how interrupts are used in an x86 CPU executing in protected mode.

Like most other CPUs, the x86 CPU has an interrupt vector table that contains information about how each interrupt should be handled. In real-mode, the x86 CPU''s interrupt vector table simply contains pointers (4 byte values) to the Interrupt Service Routines that will handle the interrupts. In protected-mode, however, the interrupt vector table contains Interrupt Gate Descriptors which are 8 byte data structures that describe how the interrupt should be handled. An Interrupt Gate Descriptor contains information about what code segment the Interrupt Service Routine resides in and where in that code segment the ISR starts. The reason for having an Interrupt Gate Descriptor instead of a simple pointer in the interrupt vector table is the requirement that code executing in user-mode cannot directly call into kernel-mode. By checking the privilege level in the Interrupt Gate Descriptor the CPU can verify that the calling application is allowed to call the protected code at well defined locations (this is the reason for the name "Interrupt Gate", i.e. it is a well defined gate through which user-mode code can transfer control to kernel-mode code).

The Interrupt Gate Descriptor contains a Segment Selector which uniquely defines the Code Segment Descriptor that describes the code segment that contains the Interrupt Service Routine. In the case of our Windows NT system call, the segment selector points to a Code Segment Descriptor in the Global Descriptor Table. The Global Descriptor Table contains all Segment Descriptors that are "global", i.e. that are not associated with any particular process running in the system (in other words, the GDT contains Segment Descriptors that describe operating system code and data segments). See figure 3 below for the relationship between the Interrupt Descriptor Table Entry associated with the ''int 2e'' instruction, the Global Descriptor Table Entry and the Interrupt Service Routine in the target code segment.

Back to the NT system call

Now after having covered the background material we are ready to describe exactly how a Windows NT system call finds its way from user-mode into kernel-mode. System calls in Windows NT are initiated by executing an "int 2e" instruction. The ''int'' instructor causes the CPU to execute a software interrupt, i.e. it will go into the Interrupt Descriptor Table at index 2e and read the Interrupt Gate Descriptor at that location. The Interrupt Gate Descriptor contains the Segment Selector of the Code Segment that contains the Interrupt Service Routine (the ISR). It also contains the offset to the ISR within the target code segment. The CPU will use the Segment Selector in the Interrupt Gate Descriptor to index into the GDT or LDT (depending on the TI-bit in the segment selector). Once the CPU knows the information in the target segment descriptor it loads the information from the segment descriptor into the CPU. It also loads the EIP register from the Offset in the Interrupt Gate Descriptor. At this point the CPU is almost set up to start executing the ISR code in the kernel-mode code segment.

The CPU switches automatically to the kernel-mode stack

Before the CPU starts to execute the ISR in the kernel-mode code segment, it needs to switch to the kernel-mode stack. The reason for this is that the kernel-mode code cannot trust the user-mode stack to have enough room to execute the kernel-mode code. For instance, malicious user-mode code could modify its stack pointer to point to invalid memory, execute an ''int 2e'' instruction and thereby crash the system when the kernel-mode functions uses the invalid stack pointer. Each privilege level in the x86 Protected Mode environment therefore has its own stack. When making function calls to a higher-privileged level through an interrupt gate descriptor like described above, the CPU automatically saves the user-mode program''s SS, ESP, EFLAGS, CS and EIP registers on the kernel-mode stack. In the case of our Windows NT system service dispatcher function (KiSystemService) it needs access to the parameters that the user-mode code pushed onto its stack before it called ''int 2e''. By convention, the user-mode code must set up the EBX register to contain a pointer to the user-mode stack''s parameters before executing the ''int 2e'' instruction. The KiSystemService can then simply copy over as many arguments as the called system function needs from the user-mode stack to the kernel-mode stack before calling the system function. See figure 4 below for an illustration of this.

What system call are we calling?

Since all Windows NT system calls use the same ''int 2e'' software interrupt to switch into kernel-mode, how does the user-mode code tell the kernel-mode code what system function to execute? The answer is that an index is placed in the EAX register before the int 2e instruction is executed. The kernel-mode ISR looks in the EAX register and calls the specified kernel-mode function if all parameters passed from user-mode appears to be correct. The call parameters (for instance passed to our OpenFile function) are passed to the kernel-mode function by the ISR.  

Returning from the system call

Once the system call has completed the CPU automatically restores the running program''s original registers by executing an IRET instruction. This pops all the saved register values from the kernel-mode stack and causes the CPU to continue the execution at the point in the user-mode code  next after the ''int 2e'' call.

Experiment

By examining the Interrupt Gate Descriptor for entry 2e in the Interrupt Descriptor Table we can confirm that the CPU finds the Windows NT system service dispatcher routine like described in this article. The code sample for this article contains a debugger extension for the WinDbg kernel-mode debugger that dumps out a descriptor in the GDT, LDT or IDT.    

Download the example code: ProtMode.zip

The WinDbg debugger extension is a DLL called ''protmode.dll'' (Protected Mode). It is loaded into WinDbg by using the following command: ".load protmode.dll" after having copied the DLL into the directory that contains the kdextx86.dll for our target platform. Break into the WinDbg debugger (CTRL-C) once you are connected to your target platform. The syntax for displaying the IDT descriptor for ''int 2e'' is "!descriptor IDT 2e". This dumps out the following information:

kd>!descriptor IDT 2e
------------------- Interrupt Gate Descriptor --------------------
IDT base = 0x80036400, Index = 0x2e, Descriptor @ 0x80036570
80036570 c0 62 08 00 00 ee 46 80
Segment is present, DPL = 3, System segment, 32-bit descriptor
Target code segment selector = 0x0008 (GDT Index = 1, RPL = 0)
Target code segment offset = 0x804662c0
------------------- Code Segment Descriptor --------------------
GDT base = 0x80036000, Index = 0x01, Descriptor @ 0x80036008
80036008 ff ff 00 00 00 9b cf 00
Segment size is in 4KB pages, 32-bit default operand and data size
Segment is present, DPL = 0, Not system segment, Code segment
Segment is not conforming, Segment is readable, Segment is accessed
Target code segment base address = 0x00000000
Target code segment size = 0x000fffff

The ''descriptor'' command reveals the following:

  • The descriptor at index 2e in the IDT is at address 0x80036570.
  • The raw descriptor data is C0   62 08 00 00 EE 46 80.
  •  This means that:
    • The segment that contains the Code Segment Descriptor described by the Interrupt Gate Descriptor''s Segment Selector is present.
    • Code running at least privilege level 3 can access this Interrupt Gate.
    • The Segment that contains the interrupt handler for our system call (2e) is described by a Segment Descriptor residing at index 1 in the GDT.
    • The KiSystemService starts at offset 0x804552c0 within the target segment.

The "!descriptor IDT 2e" command also dumps out the target code segment descriptor at index 1 in the GDT. This is an explanation of the data dumped from the GDT descriptor:

  • The Code Segment Descriptor at index 1 in the GDT is at address 0x80036008.
  • The raw descriptor data is FF FF 00 00 00 9B CF 00.
  • This means that:
    • The size is in 4KB pages. What this means is that the size field (0x000fffff) should be multiplied with the virtual memory page size (4096 bytes) to get the actual size of the segment described by the descriptor. This yields 4GB which happens to be the size of the full address space which can be accessed from kernel-mode. In other words, the whole 4GB address space is described by this segment descriptor. This is the reason kernel-mode code can access any address in user-mode as well as in kernel-mode.
    • The segment is a kernel-mode segment (DPL=0).
    • The segment is not conforming. See further reading, "Protected Mode Software Architecture" for a full discussion of this field.
    • The segment is readable. This means that code can read from the segment. This is used for memory protection. See further reading, "Protected Mode Software Architecture" for a full discussion of this field.
    • The segment has been accessed. See further reading, "Protected Mode Software Architecture" for a full discussion of this field.

To build the ProtMode.dll WinDbg debugger extension DLL, open the project in Visual Studio 6.0 and click build. For an introduction of how to create debugger extensions like ProtMode.dll, see the SDK that comes with the "Debugging Tools for Windows" which is a free download from Microsoft.

Further Reading

For information on the Protected Mode of the Intel x86 CPU there are two great sources:

1)      "Intel Architecture Software Developers Manual, Volume 3 - System Programming Guide". Available from Intel''s web site in PDF format.

2)      "Protected Mode Software Architecture" by Tom Shanley. Available from Amazon.com (published by Addison Wesley).

For more programming details about the x86 CPU, must-haves are:

1)              Intel Architecture Software Developers Manual, Volume 1 - Basic Architecture.

2)              Intel Architecture Software Developers Manual, Volume 2 - Instruction Set Reference Manual.

      Both these books are available in PDF format on the Intel web site (you can also get a free hardcopy of these two books. Volume 3 is however only available in PDF format).

About the Author

John Gulbrandsen is the founder and president of Summit Soft Consulting. John has a formal background in Microprocessor-, digital- and analog- electronics design as well as in embedded and Windows systems development. John has programmed Windows since 1992 (Windows 3.0). He is as comfortable with programming Windows applications and web systems in C++, C# and VB as he is writing and debugging Windows kernel mode device drivers in  SoftIce.  

To contact John drop him an email: John.Gulbrandsen@SummitSoftConsulting.com

About Summit Soft Consulting

Summit Soft Consulting is a Southern California-based consulting firm specializing in Microsoft''s operating systems and core technologies. Our specialty is Windows Systems Development including kernel mode and NT internals programming.

To visit Summit Soft Consulting on the web: http://www.summitsoftconsulting.com/

#include 전처리기 지시어

ex)

#include<filename> //표준 라이브러리 헤더 파일

#include"filename" //사용자 정의 헤더파일


#define 전처리기 지시어 : 기호 상수

ex)

#define 식별자  치환텍스트

#define PI 3.14159


#define 전처리기 지시어 : 매크로

ex)

#define CIRCLE_AREA(x) (PI*(x)*(x))


조건부 컴파일

#ifndef NULL //널이 정의 되지 않았다면

    #define NULL 0 //NULL을 0으로 정의

#endif //조건 디파인 종료

ex)

#if 0

    컴파일이 되지 않는 코드

#endif //주석처럼 사용 가능


#error 지시어

는 지시어에 지정된 토큰들을 포함한 시스템 구현에 의존적 메시지를 인쇄한다

ex)

#error 1 - Out of range error //#error지시어가 처리 될때 지시어에 있는 토큰들이 오류메시지로

                                        //표시되고 전처리가 중단되고, 프로그램은 컴파일 되지 않는다

#pragma 지시어

는 구현에 정의된 동작을 한다


#연산자

는 치환 텍스트 토큰을 큰따옴표로 둘러싸인 문자열로 변환

ex)

#define HELLOR(x) cout<<"Hello, " #x<<endl;

HELLO(John)은 cout<<"Hello, " "John"<<endl;로 치환됨

##연산

기호는 두개의 토큰을 연결한다

ex)

#define TOKENCONCAT(x, y) x ## y

TOKENCONCAT(O, K)는 프로그램에서 OK로 치환됨


#line 전처리기 지시어

는 뒤이어 나오는 소스 코드 줄번호를 지정된 상수 정수 값에서 시작하여 번호가 매겨지도록 함

ex)

#line 100 //다음 소스코드 줄 번호를 100부터 시작하도록


미리 정의된 기호 상수

_LINE_    현재 소스 코드 줄의 줄번호

_FILE_    소스 파일의 추정되는 이름

_DATA_    소스 파일이 컴파일된 날짜

_STDC_    프로그램이 ANSI C표준을 따르는지

_TIME_    소스 파일이 컴파일된 시간

_TIMESTAMP_    소스 파일의 최종 변경 날짜와 시간

참조 : http://www.whiteat.com/zbxe/4848



기본 지식

 

1. 병렬포트의 구조

프린트포트01.JPG
                    
그림 1 프린터 포트의 외형도



1, 14, 16, 17번은 input도 되고 output도 된다는 것을 알 수 있다.





그래서 여기서는 1, 14, 16, 17번은 사용을 안 하기로 한다.


OUTPUT

2, 3, 4, 5, 6, 7, 8, 9

INPUT

10, 11, 12, 13, 15

IN/OUT

1, 14, 16, 17

GND

18, 19. 20, 21, 22, 23, 24, 25

                           1 프린터 포트의 핀 종류



2. 병렬포트의 출력

병렬 테스트를 하기 위해 간단히 회로를 꾸며 보자.  아래의 회로도처럼 꾸민다.

프린트포트02.JPG

그림 2 프린터 포트 입력 테스트를 위한 회로도

회로도가 완성되면, PC 쪽에서 프린터 포트를 제어 해야 한다.

VC++를 사용해서 제어 하겠다. (C 보다는 VC++ 이 편하다.)

Dialog Based 로 한 다음, 버튼을 하나 만들고, 그 버튼 메시지 아래와 같은 코드를 입력

for(int i=0;i<256;i++)  {

_outp(0x378,i);

for(int j=0;j<10000;j++);

} 

그리고 버튼을 누르면  병렬포트에 연결시켰던 LED들이 우르르~ 켜지는 것을 볼 수 있다.

(하지만, win2000 이상에서는 잘 안될 것이다.)

그래서 다른 방법을 써야 한다.  라이브러리를 사용해야 한다.

라이브러리를 사용하면  2000 이하의 버전에서도 사용이 가능하므로, 라이브러리를 사용해서 하는게 좋을 것이다. (나중에 자세히 설명한다.)

 

파일은 자료실에 있다.

     _outp(0x378,i); 함수에서,

0x378 LPT1일때 즉 프린터포트의 주소이고,  그 뒤의 값은 데이터 값이다.

, 2번부터 9번까지(Data0 부터 Data7까지)데이터를 출력해 준다.

예를들어,  _outp(0x378,9)라고 했다면,
9 2진수로 1001이므로 2번핀과 5번핀이 HIGH 로 된다.



cf. 라이브러리를 이용한 제어

http://www.driverlinx.com/ 에 자세한 설명이 있고,

라이브러리를 제작, 배포하는 곳이다. 다운 받으려면 가입을 해야 하지만

http://www.driverlinx.com/DownLoad/DlPortIO.htm 여기에서 그냥 받을 수 있다.

또는 자료실 (http://rtcontrol00.ee.hallym.ac.kr ) 에 있다.

 

port95nt.exe Port I/O Driver (1,573k)

를 다운 받아 설치한다. 다 끝나면 (꼭 리붓을 해야 한다.)

프린트포트03.JPG

그림 3 생성된 단축 아이콘



그림의 C++ PortIO 를 실행하면

프린트포트04.JPG    프린트포트05.JPG                  

그림 4 실행초기 화면                   

그림 5 프린터 포트를 쓰는 화면

프린터 포트를 쓰는 그림에서 Write 를 누르면 프린터 포트에 데이터를 쓰는 것이다.

0x378 은 프린터 포트를 쓰는 주소이고, 0은 데이터 이다.

즉 프린터 포트에 0을 쓰는 것이다.

값을 읽을 때에는 Read 를 누르면 된다.

일단 여기서 에러 없이 잘 되면, 프린터 포트 제어에 문제가 없는 것이다.

이제 자신의 코드를 만들어 보자. VC6.0++ 을 이용하겠다.


VC++로 라이브러리 추가하여 프로그램 짜기

다이러로그 방식으로 프로그램을 짜서 버튼을 만들고 메시지를 연결한다.

라이브러리를 연결해야 하는데,

우선, 라이브러리를 사용할 폴더로 복사한다. [ Dlportio.h 파일과 Dlportio.lib 파일 ]

프린트포트06.JPG

설치된 폴더에서 API 폴더에 있다.

 

그리고, 라이브러리를 연결하고, 헤더파일을 추가한다.

(VC++ 에 대한 설명은 생략한다.)

 

그리고 코드를 연결한다.

 

void CPTESTDlg::OnButton1() {

             for(int i=0;i<256;i++)  {

                           DlPortWritePortUchar(0x378,i);

                           Sleep(1);

             }           

}DlPortWritePortUchar() 함수는 포트에 값을 쓰는 함수이다.

함수를 알아보려면 Dlportio.h 를 열어 보기 바란다.(절대 수정하지는 말고 ^^;; )

 

그리고 버튼을 누르면 LED 가 빠르게 깜빡거릴 것이다.


dlportio.h 파일을 보면 다음과 같은 함수가 있다.

<Read 함수>
DlPortReadPortUchar(IN ULONG Port);
DlPortReadPortUshort(IN ULONG Port);
DlPortReadPortUlong(IN ULONG Port);
DlPortReadPortBufferUchar(IN ULONG Port,IN PUCHAR Buffer,IN ULONG Count);
DlPortReadPortBufferUshort(IN ULONG Port,IN PUSHORT Buffer,IN ULONG Count);
DlPortReadPortBufferUlong(IN ULONG Port,IN PULONG Buffer,IN ULONG Count);

<Write 함수>
DlPortWritePortUchar(IN ULONG Port,IN UCHAR Value);
DlPortWritePortUshort(IN ULONG Port,IN USHORT Value);
DlPortWritePortUlong(IN ULONG Port,IN ULONG Value);
DlPortWritePortBufferUchar(IN ULONG Port,IN PUCHAR Buffer,IN ULONG Count);
DlPortWritePortBufferUshort(IN ULONG Port,IN PUSHORT Buffer,IN ULONG Count);
DlPortWritePortBufferUlong(IN ULONG Port,IN PULONG Buffer,IN ULONG Count);

 

뒤에 붙은 char(1byte), short(2byte), long(4byte) 은 데이타 타입이다.

자주 사용하는 함수는  DlPortReadPortUchar(), DlPortWritePortUchar() 이고, 바이트 단위로 통신하는 것이다
.
 

이제부터 라이브러리를 사용한다고 가정하고 설명하겠다.



3. 병렬포트의 입력

parallel port를 통해 입력을 받아보기 위해 회로를 꾸미자.

 

프린트포트07.JPG

그림 6 입력과 출력 회로도

주의 사항

최상위 비트는 11번이다.

11,10,12,13,15번 순이다. 주의 요

 

입력 버튼을 만들고, 코드를 넣자.

void CPTESTDlg::OnButton2() {

             int a=DlPortReadPortUchar(0x379);

             m_strData.Format("%x",a);

             UpdateData(FALSE);

}

 

테스트를 해 보면 11(최상위) 핀은 반전되어서 나오는 것을 알수 있다.

( 뒤쪽의 3비트는 I/O 공동으로 사용한 데이터 같은데 뭔지 모르겠음)

입력 값

PC 에서 읽은 값

1111 1XXX

0111 1XXX

0000 0XXX

1000 0XXX

1010 1XXX

0010 1XXX

0110 0XXX

1110 0XXX



실시간으로 프린트 포트로부터 입력 받기

약간의 C++ 지식이 필요하다.

일단 소스를 보면

void CPTESTDlg::OnButton2() {

        // 실시간으로 프린터 포트의 입력 값을 읽어서 화면에 보여줌

             while(1){

                           MSG msg;

                           while(::PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)){

                                        switch(msg.message){

                                        case WM_QUIT:

                                        case WM_DESTROY:

                                        case WM_CLOSE:

                                                     PostQuitMessage(0);

                                                     return ;

                                        }

                                        ::TranslateMessage(&msg);

                                        ::DispatchMessage(&msg);

                           }

                          

                           int a=DlPortReadPortUchar(0x379);

                           m_strData.Format("%x",a);

                           UpdateData(FALSE);

             }

}

그리고 종료 할 때,

PostQuitMessage(0);

를 꼭 해주어야 한다. 그렇지 않으면 리소스를 반납하지 않기 때문에, PC 가 느려진다.

 

꼭 리소스가 제대로 반납되는지 확인 하기 바란다.




<참고> ECP , EPP 모드에 관해

하이텔 :신동익  (kbread  )님께서 쓰신 글입니다.

안녕하세요.
프린터포트로 뭔가를 하려는 분이 많이 계신가본데,제가 얼마 전에 인터넷에서
자료를 좀 구했습니다.

보통 centronics라고 불리우는 일반적인 프린터 포트 방식으로는 4bit의 데이타를 그것도 출력으로만 사용할 수 있지요.

최근에는 외장 하드디스크나 zip drive 등 대용량, 고속으로 동작하는 외부기기를 프린터포트에 접속하여 사용하는 경우가 늘고 있습니다. 따라서 병렬포트(프린터 포트보다 치기가 쉬워서)도 기존의 규격으로는 부족한 감이 있지요.

그래서 기존의 모드를 그대로 지원하면서, 고속의 확장모드를 지원할 수 있도록  새로운 규격의 병렬포트가 등장한 겁니다. 이른바 EPP, ECP라는 것 말입니다.

EPP Enhanced Parallel Port의 약자로서 프린터를 제외한 고속, 대용량(외장 하드, 캐너 등)의 외부기기를 지원하는 모드입니다. 8bit의 데이타 버스를 양방향으로 이용할 수 있습니다.

ECP Extended Compatibility Port의 약자로서 프린터로의 데이타 전송을 고속화 하려는 목적으로 고안된 것입니다. 마찬가지로 8bit의 양방향 통신을 할 수 있습니다. 최근의 레이저 프린터들은 대개 이 모드를 지원합니다.

또한 이러한 모드를 이용하기 위해서는 PC에 이 모드를 지원하는 병렬포트가 장착되어 있어야 하는데, PC의 부팅 시 cmos setup에 들어가서 지원여부를 확인할 수 있습니다. setup menu에서 communication port쪽을 살펴보면, com1은 어쩌구, com2는 저쩌구, lpt1은 어쩌구 에서 LPT부분의 메뉴를 변경해 보면 normal, ECP, EPP, ECP+EPP등이 나타나면 이게 지원되는 보드입니다.

ECP 모드에서의 전송 속도는 500Kbyte/sec에서 최대 2MByte/sec까지 가능합니다.
이 정도의 속도라면 보통 ISA bus에 인터페이스 한 것과 거의 대등한 속도라고 봅니다. 그리고 프로토콜도 매우 간단해서 프린터포트 인터페이스를 해 보신 분이라 면 누구나 쉽게 할 수 있습니다.

보다 자세한 규격은 인터넷주소 http://www.fapo.com/ieee1284.htm에 있습니다.
참고로 ECP, EPP를 지원하는 병렬포트 규격을 IEEE1284라 합니다.

<출처 : 2001.10.15 | HiTEL Windows 동호회(k2win4@hitel.net)>

외국에 유학한 유학생이나 외국계 기업에 다니는 회사원, 외국에 수출하는 소프트웨어를 개발하는 프로그래머라는 세 계층은 척 보기엔 큰 공통점이 없어 보인다. 외국자 들어가는 것 빼고는. 하지만 이들은 공통적인 문제점을 하나 안고 있다. 사람은 한국인인데 컴퓨터의 운영체제는 영문 운영체제를 써야 하는 일이 생긴다는 것이다. 아무리 영어를 잘 아는 사람이라 할지라도 영문 운영체제는 한글 운영체제보다 작업 효율성은 떨어질 수 밖에 없다. 결국 불편을 감수하면서 영문 운영체제를 사용해야 하거나 한글 운영체제와 다중 부트 형식으로 사용할 수 밖에 없다.(VMWare와 같은 방식은 논외로 하자. 보통 사람은 잘 사용하지도 않는 방식이므로......)

상식적으로 생각해보면 두개의 운영체제를 필요에 따라 서로 바꾸어가며 부팅하는 것이 가장 좋아 보인다. 그러나 이 방법도 문제가 없는것은 아니다. 운영체제를 두개 설치하는 시간도 시간이지만 공간 낭비도 무시할 수 없다. 같은 소프트웨어를 따로 설치해주어야 하므로 이래저래 불편한 것은 아니다.(머리를 쓰면 이것도 최소화 할 수 있지만 크게 줄진 않는다.) 어차피 한 사람이 운영체제를 2개 사용하는 것인데 이것은 너무 커다란 불편이요 낭비이다.(배부른 소리라고 말하는 것은 상관 없다. 다음 글을 다 읽은 후에.)


앞에서 낭비, 낭비라고 외치는데 그러면 방법이 있는가? 방법이 있으니까 이런 소리라도 할 수 있는 것이다. 이러한 불편함을 없앨 수 있는 획기적인 방법을 Microsoft에서는 제공하고 있다. 불가능을 가능케 하는 비법, 그것이 바로 MUI 팩이다.




 MUI란 무엇인가?


MUI는 Multilingual User Interface의 약자이다. 한글로 굳이 쓰자면 다국어 사용자 인터페이스정도로 번역될 것인데 이것은 하나의 운영체제에 언어와 인터페이스만 바꾸어 주는 기능을 말한다.


쉽게 말해보자. 일반적으로 영문 운영체제라 한다면 시작 메뉴부터 안에 포함된 기본 소프트웨어, 글꼴, 키보드 및 마우스, 도움말이 모두 영문으로 표시되며 한글이나 일본어, 중국어, 아랍어는 정상적으로 표시되지 않는 운영체제를 말할 것이다. Windows 2000이 되면서 적어도 영문 운영체제에서 다른 언어를 보고 입/출력하는 것은 어느정도 융통성이 생기게 되었지만 여전히 기능과 애플리케이션은 영문판이다. 이것만으로도 사용상 불편함을 느끼기엔 매우 충분하다. MUI 패키지는 이 영문판 운영체제를 문자 입/출력 시스템부터 메뉴, 애플리케이션, 도움말까지 모두 한글화 또는 일본어, 중국어, 아랍어화 시킬 수 있다. 거의 완벽한 한글, 일본어, 중국어, 아랍어 Windows로 탈바꿈 할 수 있는 것이다.


 MUI 패키지에 대한 몇가지 의문점


영문판 운영체제를 쉽게 한글판, 일본어판, 중국어판 운영체제로 바꿀 수 있다는 점은 귀가 솔깃한 이야기가 될 것이다. 하지만 무조건 기뻐하기 전에 몇가지 의문점이 들 것이다. 일반적으로 MUI 패키지에 대해 많은 사용자가 문의하는 점에 대해 간략히 정리하여 보았다.


문 : MUI 패키지를 한글 Windows에 설치하면 영문, 일본어, 중국어 Windows가 됩니까?


답 : 그렇지 않습니다. MUI 패키지는 영문 운영체제에만 설치할 수 있습니다. 기타 언어 운영체제에는 설치할 수 없습니다.


문 : 저는 Windows XP Home Edition 영문판을 이용합니다. 여기에 Windows 2000 MUI를 설치할 수 있는지요?


답 : 설치할 수 없습니다. MUI는 Windows의 버전에 따라 내용물이 전혀 달라지므로 이전 버전 또는 이후 버전의 MUI는 사용할 수 없습니다. 또한 Windows XP의 경우 Home Edition은 MUI 패키지를 설치할 수 없습니다.


문 : MUI 패키지는 어디에서 구입할 수 있습니다.


답 : 시중에서는 MUI 패키지를 구입하실 수 없습니다. 원칙적으로 MUI 패키지는 이러한 환경에 있는 기업에만 특별히 공급되며 시중에서 따로 판매되진 않습니다. MUI의 구입은 각 국가의 Microsoft 지사에 문의하여 주십시오.


문 : MUI 패키지는 어느정도의 디스크 공간을 사용합니까?


답 : 얼마나 많은 언어의 MUI를 설치하는가에 따라 다릅니다만 최소 100MB에서 500MB까지의 추가적인 디스크 공간을 요구합니다. 용량이 큰 것처럼 보이지만 실제 2개 이상의 운영체제를 설치하는 용량에 비해서 훨씬 작은 크기입니다.


 MUI의 설치


Windows XP MUI를 설치하기 위해서는 일단 영문판 Windows XP Professional과 추가적인 디스크 공간이 필요하다. 준비가 되었다면  Windows XP MUI 패키지 CD를 넣는다.



 


 MUI 패키지의 CD를 넣으면 설치 화면이 시작된다. 이 화면은 사용자 계약서로서 반드시 한번은 읽어 보아야 할 정보를 담는다.(특히 MS의 사용자 계약서는 법률과 법률로 얽힌 법률의 함정이라 볼 수 있을 정도로 애매모호하고 나중에 문제가 될 수 있는 부분이 많다.) 철저히 읽고 동의할 경우 동의하는 항목에 체크를 하고 다음으로 넘어간다.



 


 설치할 언어 팩을 고르고 기본 언어를 설정한다. 한국인이라면 당연히 Korean에 체크를 할 것이고 필요하다면 일본어나 중국어(간체/번체), 독일어 등에도 체크를 한다. 또한 밑의 Default User Settings에서 기본 언어를 설정한다. 한글 입/출력을 원한다면 Korean으로 설정하고 OK를 누른다.



 


 일단 Windows XP 원본에서 각 언어에 맞는 입/출력 시스템을 복사/설치한다. Windows XP 원본 CD를 준비한다. 이 작업은 몇분정도 소요된다.



 이제 Windows XP MUI 패키지에서 UI 파일을 설치한다. 이 작업은 몇분에서 몇십분까지 걸릴 수 있으나 일반적인 시스템이라면 몇분내로 복사가 완료된다.




 복사 작업이 완료되면 복사가 완료되었다는 창이 표시된다. OK를 누르면 재부팅을 요구하므로 재부팅을 하도록 한다.


 언어를 변경하자


설치하고 재부팅을 해도 영문 Windows 상태에서 변함은 없다. MUI 패키지는 과연 가짜인가? 그렇지는 않다. 지금부터 UI를 변경하는 방법에 대해 간략히 살펴보기로 하자.



 제어판(Control Panel)에 가면 국가별 설정 항목으로 들어간다.



 이 항목에는 3가지 탭이 있는데 일단 Regional Options 탭에 있는 Standards and Formats와 Location 항목이 정상적으로 한국(또는 설정을 변경하고자 하는 언어를 사용하는 국가)으로 되어 있는 지 확인한다. 이 부분은 UI 변경과 관계는 없으나 단위 표시 및 정보 제공에 중요한 역할을 한다.



 Languages 탭으로 이동하면 맨 하단에 Language used in menu and dialogs 항목이 나타난다. 여기에는 추가한 MUI의 언어가 표시되는데 사용자가 원하는 언어로 변경한다. 변경 후 OK 또는 Apply를 눌러 적용한다.



 현재 사용자의 로그 오프를 해야 적용된다는 메시지가 표시된다. 재부팅 또는 사용자 로그 오프를 해준다. 이렇게 하면 설정된 언어로 모든 UI가 변경된다. 변경되기 전 UI와 변경된 UI의 차이를 아래에서 볼 수 있다.



 

 MUI의 장점과 단점


 장점


 요구되는 디스크 공간을 최소화 할 수 있다. 일반적으로 두가지 언어의 Windows를 독자적으로 설치하려면 최소한 300MB, Windows NT 계열 운영체제는 이보다 훨씬 많은 공간을 요구한다. 하지만 MUI를 설치할 경우 100MB 내외의 공간 점유만을 하므로 적은 디스크 공간에서도 최대한의 효율성을 발휘한다.


 언어의 전환이 매우 빠르다. 다중 부트의 경우 최소한 한번 재부팅을 하여야 하고 2개의 디스크를 이용할 경우 경우에 따라 BIOS에서 부팅 순서를 변경해야 하는 번거로움이 생기지만 MUI를 사용할 경우 언어 전환 후 로그 오프만으로도 언어를 쉽게 변경할 수 있다.


 일반적으로 타 언어 OS에서는 한글의 표시와 입/출력에 제한을 받는다. Windows 2000 이후의 운영체제는 이러한 제한이 좀 줄어들었으나 여전히 불편함은 남아 있는데 MUI를 사용하면 타 언어 Windows 상황에서도 언어의 입/출력이 자유롭다. 예를 들어 중국어 Windows에서 '우리나라 만세'라는 한글을 어디서든 쉽게 쓸 수 있다.


 단점


 MUI는 웬만한 프로그램과 도움말을 다른 언어로 바꾸어준다. 하지만 모든것을 다른 언어로 바꾸어주진 못하며 일부분은 여전히 영문 Windows 상태 그대로가 된다. 예를 들자면 장치 관리자의 경우 언어를 바꾸어도 여전히 영문으로 남는다.


 글꼴 또한 기본적으로 영문 글꼴로 표시되는 경우가 많다. 그러므로 한글 또는 표준 일본어 글꼴에 익숙해진 사용자라면 익숙하지 않은 영문 글꼴의 모양에 거부감을 느낄 수 있다.

+ Recent posts