|
도움이 될런지 모르겠네요...
델파이에서 윈도우디바이스와 직접통신하시보단 비주얼C++에서 디바이스통신DLL을 만들어
델파이에서 호출하는 방식이 좋을것 같네요..
샘플입니다. 올리신 소스일부를 고쳐봤읍니다.
NTSTATUS DeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PAGED_CODE();
PIO_STACK_LOCATION IrpStack;
NTSTATUS ntStatus = STATUS_SUCCESS;
ULONG inBufLength;
ULONG outBufLength;
PCHAR inBuf, outBuf;
PCHAR data = "Hello DDK World!!";
ULONG datalen = strlen(data)+1;
// 스택 로케이션은 사용자 버퍼의 정보를 갖고 있다
IrpStack = IoGetCurrentIrpStackLocation(Irp);
inBufLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
//DeviceIOControl에서 넘어오는 버퍼의 구함
outBufLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
switch ( IrpStack->Parameters.DeviceIoControl.IoControlCode )
{
case IOCTL_PID_READ:
//#define IOCTL_PID_READ
// CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS )
// 위의 정의에서 버퍼를 READ,WRITE,READ_WRITE할지를 정의할수 있죠....
// 디바이스드라이브에 하나정의, APP에서도 같은게 하나 정의되죠...
inBuf = Irp->AssociatedIrp.SystemBuffer;
// DeviceIOControl을 통해서 내려온 App메모리주소 입니다
outBuf = Irp->AssociatedIrp.SystemBuffer;
// DeviceIOControl을 통해서 내려온 App메모리주소 입니다.
strncpy(outBuf, data, outBufLength);
Irp->IoStatus.Information = (outBufLength<datalen?outBufLength:datalen); //데이터길이 열나 중요
Irp->IoStatus.Status = ntStatus;
break;
default:
ntStatus = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Status = ntStatus;
break;
}
DbgPrint("[+]23");
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint("[+]24");
//DbgPrint("DeviceControl 3");
return ntStatus;
}
----------------------------------------------------------------
APP에선
char OutputBuffer[100];
char InputBuffer[100];
ULONG bytesReturned;
strcpy(InputBuffer, "This String is from User Application; using METHOD_BUFFERED");
printf("\nCalling DeviceIoControl METHOD_BUFFERED:\n");
memset(OutputBuffer, 0, sizeof(OutputBuffer));
bRc = DeviceIoControl ( hDevice,
(DWORD) IOCTL_PID_READ,
&InputBuffer,
strlen ( InputBuffer )+1,
&OutputBuffer,
sizeof( OutputBuffer),
&bytesReturned,
NULL
);
미미나리 님이 쓰신 글 :
: 주언어 델파이 초보 개발자가 아직 c언어에 익숙하지 않아 무지 고생입니다.
:
: 제가 하고 싶은 일은 델파이 APP와 sys 파일간의 DeviceIOControl을 이용해서 통신하는 것인데요,
:
: 우선 APP과 sys 가 주고 받는 코드는
: #define IOCTL_PID_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS )
: 로 정의 되어있고, sys에서 담아줄수 있는 데이터는 프로세스 아이디와 프로세스 이름입니다.
:
: static CHAR str1[1000];
: //static STRING str1; <- 이거 해보고
: //static LPSTR str1; <- 이거 해보고
: static LPSTR str;
: static PVOID str2;
:
: 삽질 끝에 스트링 값을 변수에 집어넣는건 원하는 데이터 대로 디버깅을 통해 확인이 되었는데
:
: 이렇게요....
:
: str = (CHAR *) (i + 16 + PID_OFFSET + NAME_OFFSET);
: strcat(str1, str);
: strcat(str1,"|");
:
: =>wuauclt.exe|ALZip.exe|editplus.exe|alg.exe|cmd.exe|Dbgview.exe|InstDriver.exe|iexplore.exe|explorer.exe|ctfmon.exe|svchost.exe|svchost.exe|spoolsv.exe|svchost.exe|svchost.exe|conime.exe|svchost.exe|lsass.exe|services.exe|winlogon.exe|csrss.exe|smss.exe|System|
:
: 이런식으로만 넘어와도 델파이 App 에서 가공하는 건 일도 아니겠죠.
:
: 아무튼 이걸 출력버퍼(driver -> app)에 담아줘야한다는 건데 데이터형에서 무지 헷갈립니다.
:
: 어쩌면 좋을까요?
: sendmessage 같은건 어떻게 쓰는지 뭘 include 해줘야 하는지도 모르겠고;;
:
:
: NTSTATUS DeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
: {
: PAGED_CODE();
: PIO_STACK_LOCATION IrpStack;
: NTSTATUS ntStatus = STATUS_SUCCESS;
: PVOID outBuf;
: // 스택 로케이션은 사용자 버퍼의 정보를 갖고 있다
: IrpStack = IoGetCurrentIrpStackLocation(Irp);
: switch ( IrpStack->Parameters.DeviceIoControl.IoControlCode )
: {
: case IOCTL_PID_READ:
:
: ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
: LPSTR pPid;
: pPid = (LPSTR) Irp->AssociatedIrp.SystemBuffer; // Irp->AssociatedIrp.SystemBuffer는 PVoid 형 입니다.
: *(pPid) = str1
: ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
: //이부분입니다.
: Irp->IoStatus.Information = 123;
: Irp->IoStatus.Status = ntStatus;
: break;
:
: default:
: ntStatus = STATUS_INVALID_DEVICE_REQUEST;
:
: break;
: }
: DbgPrint("[+]23");
: IoCompleteRequest(Irp, IO_NO_INCREMENT);
: DbgPrint("[+]24");
: //DbgPrint("DeviceControl 3");
: return ntStatus;
: }
: 처음부터 로직이 이상한 건가요?
: 일주일 넘게 데이터형만 바꿔보고 있습니다.
: 커널 디버깅은 할줄도 모릅니다. 좀 도와주십시오.
|