2009년 11월 24일 화요일

[2010 시간관리페스티벌] High Performer's Secret

 

관련 페이지 : http://www.franklinplanner.co.kr/tmf/2010/default.aspx

 

프랭클린플래너에서 "시간관리 페스티벌"을 개최합니다!

 

제가 생각하는 Hight Performer는 시간을 효율적으로 사용할 줄 알고, 현재를 즐길 줄 아는..

그런것이 아닐까 생각되는데요^^

 

아직 시간관리를 효율적으로 하지 못하고, 대화에 있어서도 부족한 점이 많은데 "시간관리 페스티벌"을 통해 부족한 점을 배우고 Hight Performer로서 나아가는 걸음이 되었으면 좋겠습니다.

 

여러분도 함께 참여해보시는 것은 어떠세요?!

 

 

2009년 11월 8일 일요일

TransmitFile()에 대해서..

BOOL TransmitFile (
     SOCKET hSocket,
     Handle hFile,
     DWORD를 nNumberOfBytesToWrite,
     DWORD를 nNumberOfBytesPerSend,
     LPOVERLAPPED lpOverlapped,
     LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,
     DWORD를 dwFlags
);

첫번째 인자 : 파일을 전송할 소켓의 핸들

 

두번째 인자 : 전송할 파일의 핸들 (반드시 FILE_FLAG_SEQUENTIAL_SCAN 속성이 주어져야 한다. 이 속성은 파일을 처음부터 끝까지 순차적으로만 접근한다는 의미이다.)

세번째 인자 : 전송할 파일의 크기 (0으로 하면 파일 전체를 전송)

네번째 인자 : 파일을 전송할 때 내부적으로 ::send()함수를 사용하며 이때 버퍼의 크기를 얼마로 할것인지 명시하는 것.

 

다섯번째 인자 : OVERLAPPED 구조체에 대한 포인터(네트워크 입/출력을 비동기적으로 처리할 수 있도록 하였다면 이부분도 지원해 준다. 동기적 처리는 NULL)

여섯번째 인자 : TRANSMIT_FILE_BUFFERS 구조체에 대한 포인터(NULL 이면 파일 내용만 전송)

마지막 인자 : 기타 옵션

[ TF_DISCONNECT : 전송 작업이 완료되면 트랜스포트 레벨 접속을 끊는다.

TF_REUSE_SOCKET  : 전송 작업이 완료된 이후에 소켓을 재사용 할 수 있도록 한다.

                                    이 소켓은 AcceptEx 함수에 의해 재활용 될 수 있다. 이 플래그

                                    는 TF_DISCONNECT와 함께 사용해야함.

TF_USE_DEFAULT_WORKER : 시스템 디폴트 스레드를 이용해서 파일을 전송한다.

                                                이 플래그는 큰 파일을 전송할 때 유용하다.

TF_USE_SYSTEM_THREAD : 시스템 스레드를 이용해서 파일을 전송한다.

TF_USE_KERNEL_APC : 전송 작업을 처리하는데 커널 APC를 사용한다. 커널 APC는

                                       응용프로그램이 대기 상태일 때 작동된다.(경고성 대기 상태

                                       일 필요는 없다).

TF_WRITE_BEHIND : TrnasmitFile 호출이 데이터가 전송 완료되기 전에 리턴된다. TF_DISCONNECT나 TF_REUSE_SOCKET 플래그와 함께 사용할 수 없다.]

 

Stdafx.h 파일을 열어서 ::TransmitFile() 함수에 대한 정보가 담긴 헤더와 라이브러리 설정 코드를 추가한 다음 결과를 확인한다!

 

#include <Mswsock.h>

#pragma comment(lib, "Mswsock.lib")

 

어떻게 사용했냐..간단히 함수 부분만 넣어보겠다.

 

ret = TransmitFile(ClientSock, hFileSource, (DWORD)0, 15000, NULL, NULL, 

                           TF_DISCONNECT);
   if (ret == SOCKET_ERROR)
   {
             strTmp.Format("TransmitFile error code : %d", WSAGetLastError());
              AfxMessageBox(strTmp);
   }
   else {
              strTmp = "파일 전송이 완료되었습니다.";
               InsertChatStr(strTmp,3);
   }

Winsock 에러 코드!

작년에 TCP/IP 책을 통해 네트워크를 공부하는데 실습을 많이 하지 못해서..네트워크 프로그램 개발하려고 하니 하나도 생각 안나네요..ㅡ_ㅡ
 
역시 공부할 때에 실습을 꼭꼭 많이~ 병행하는 것이 좋겠습니다..
 
이 글은 MFC에서 Winsock사용해서 프로그래밍 할 때 발생하는 에러 코드 보기 위해..!
 
 
===================================================================
WSAEBADF 10009
잘못된 기술자(소켓 핸들)이다

WSAEACCES 10013
브로드캐스트 어드레스를 위한 데이터그램 소켓의 접속시도가 setsockopt 함수로 SO_BROADCAST가 설정되어있지 않은 상태에서 실패 했습니다.

WSAEFAULT 10014
name 또는 namelen 매개변수가 올바른 형태가 아닙니다.
 
WSAEINVAL 10022
accept 하기 전에 listen 함수가 불려지지 않았습니다.
 
WSAEMFILE 10024
새로운 소켓에 할당하기 위한 소켓 기술자가 더 이상 남아있지 않습니다
 
WSAEWOULDBLOCK 10035
소켓 함수가 비블럭킹 모드로 동작중이다

WSAEINPROGRESS 10036
블록화 함수가 호출 되는 동안 부적절한 소켓 함수가 호출되었다
 
WSAEALREADY 10037
이미 완료된 비동기 명령에 대한 취소가 시도됨
 
WSAENOTSOCK 10038
지정한 기술자가 소켓 기술자가 아닙니다
 
WSAEDESTADDRREQ 10039
해당 함수에 목적지 어드레스가 필요하지만 제공되지 않았음
 
WSAEMSGSIZE 10040
수신된 메시지가 지정된 버퍼에 저장하기에 너무 커서 손실 되었습니다
 
WSAEPROTOTYPE 10041
지정된 프로토콜이 잘못되었거나 이 소켓에 대해서 잘못된 형식입니다
 
WSAENOPROTOOPT 10042
알 수 없는 옵션이거나, 지원지지 않는 옵션을 사용했습니다.
 
WSAEPROTONOSUPPORT 10043
지정된 프로토콜이 지원되지 않는 형식입니다
 
WSAESOCKTNOSUPPORT 10044
지정된 소켓 타입이 지정한 어드레스 체계에서 지원되지 않는 형식입니다
 
WSAEOPNOTSUPP 10045
socket이 연결지향형 서비스(SOCK_STREAM)형태가 아닙니다. ex) listen이 UDP socket에서 호출
 
WSAEPFNOSUPPORT 10046
지정된 프로토콜 체계가(PF_*) 지원되지 않습니다
 
WSAEAFNOSUPPORT 10047
지정된 어드레스 체계가(AF_*) 지원되지 않습니다
 
WSAEADDRINUSE 10048
지정한 어드레스(IP)가 이미 사용중이다
 
WSAEADDRNOTAVAIL 10049
지정된 어드레스는 로컬 머신에서 사용할 수가 없다

WSAENETDOWN 10050
네트웍 서브 시스템에 에러가 발생했습니다
 

WSAENETUNREACH 10051
원격 시스템까지 네트웍이 도달할 수 없습니다
 

WSAENETRESET 10052
연산이 진행되고 있는 도중 접속이 끊겨버렸습니다.
 

WSAECONNABORTED 10053
연결이 out-of-band나 다른 실패 때문에 끊어져 버렸습니다.
 

WSAECONNRESET 10054
원격 연결지에서 "hard"나 "abortive" 종료를 수행해서 리셋되었습니다.
 

WSAENOBUFS 10055
윈도우 소켓 시스템의 버퍼 공간이 모자라거나, 애플리케이션에 의해 API에게 제공된 공간이 너무 작아서 요청된 정보를 저장 할 수가 없음
 

WSAEISCONN 10056
지정된 소켓이 이미 연결 되어 있음
 

WSAENOTCONN 10057
지정된 소켓이 이미 연결 되어 있지 않음
 

WSASHUTDOWN 10058
소켓이 셧다운(shutdown()) 되었습니다.
 

WSAETOOMANYREFS 10059
지정한 함수에 대한 인자가 너무 많음
 

WSAETIMEDOUT 10060
접속 시도가 시간초과 되었습니다.
 

WSAECONNREFUSED 10061
접속시도가 강제로 종료되었습니다
 

WSAELOOP 10062
Too many levels of symbolic links.

Answer/Solution: A pathname lookup involved more than eight symbolic links. (Too many links were encountered in translating a pathname.)

 

 


WSAENAMETOOLONG 10063
 File name too long.
Answer/Solution: A component of a path name exceeded 255 (MAXNAMELEN) characters, or an entire path name exceeded 1023 (MAXPATHLEN-1) characters
 
 
WSAEHOSTDOWN 10064
원격 호스트가 다운 되었음
 Answer/Solution: The problem may be due to one of the following:
  • A socket operation failed because the destination host was down.

  • A socket operation encountered a dead host.

  • Networking activity on the local host has not been initiated.


WSAHOSTUNREACH 10065
네트웍 시스템 장애 등에 의해서 원격호스트까지 도달 할 수 없습니다.
 Answer/Solution: A socket operation was attempted to an unreachable host.
 

WSASYSNOTREADY 10091
네트워크 서브 시스템이 아직 통신할 준비가 되어 있지 않음(WSAStartup()이 반환)
 Answer/Solution: The Winsock implementation cannot function at this time, because the underlying system it uses to provide network services is currently unavailable.
 
 

WSAVERNOTSUPPORTED 10092
요청한 윈도우즈 소켓 버전이 현재 윈도우즈 소켓 시스템에서 지원하지 않습니다.
 

WSANOTINITIALISED 10093
이 함수를 사용하기 전에 성공적인 WSAStartup 함수의 호출이 없었습니다.
 

WSAHOST_NOT_FOUND 11001
호스트를 찾아낼 수 없습니다.
 

WSATRY_AGAIN 11002
요청된 정보가 발견 되지 않음
 

WSANO_RECOVERY  11003
회복할 수 없는 에러발생
 

WSANO_DATA 11004
잘못된 이름(name)으로 아무런 데이터가 기록되지 않았습니다. 

[소스분석] WDF sample source - Osrubsfx2 : device.c

/*++

Copyright (c) Microsoft Corporation.  All rights reserved.

    THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
    KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
    PURPOSE.

Module Name:

    Device.c

Abstract:

    USB device driver for OSR USB-FX2 Learning Kit

Environment:

    Kernel mode only


--*/

#include <osrusbfx2.h>

#if defined(EVENT_TRACING)
#include "device.tmh"
#endif

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, OsrFxEvtDeviceAdd)
#pragma alloc_text(PAGE, OsrFxEvtDevicePrepareHardware)
#pragma alloc_text(PAGE, OsrFxEvtDeviceD0Exit)
#pragma alloc_text(PAGE, SelectInterfaces)
#pragma alloc_text(PAGE, OsrFxSetPowerPolicy)
#pragma alloc_text(PAGE, OsrFxReadFdoRegistryKeyValue)
#endif


NTSTATUS
OsrFxEvtDeviceAdd(
    __in WDFDRIVER        Driver,
    __in PWDFDEVICE_INIT  DeviceInit
    )
/*++
Routine Description:

    EvtDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager. We create and initialize a device object to
    represent a new instance of the device. All the software resources
    should be allocated in this callback.

Arguments:

    Driver - Handle to a framework driver object created in DriverEntry

    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

    NTSTATUS

--*/
{
    WDF_PNPPOWER_EVENT_CALLBACKS        pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES               attributes;
    NTSTATUS                            status;
    WDFDEVICE                           device;
    WDF_DEVICE_PNP_CAPABILITIES         pnpCaps;
    WDF_IO_QUEUE_CONFIG                 ioQueueConfig;
    PDEVICE_CONTEXT                     pDevContext;
    WDFQUEUE                            queue;

    UNREFERENCED_PARAMETER(Driver);

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"--> OsrFxEvtDeviceAdd routine\n");

    //
    // Initialize the pnpPowerCallbacks structure.  Callback events for PNP
    // and Power are specified here.  If you don't supply any callbacks,
    // the Framework will take appropriate default actions based on whether
    // DeviceInit is initialized to be an FDO, a PDO or a filter device
    // object.
    //

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
    //
    // For usb devices, PrepareHardware callback is the to place select the
    // interface and configure the device.
    //
    pnpPowerCallbacks.EvtDevicePrepareHardware = OsrFxEvtDevicePrepareHardware;

    //
    // These two callbacks start and stop the wdfusb pipe continuous reader
    // as we go in and out of the D0-working state.
    //

    pnpPowerCallbacks.EvtDeviceD0Entry = OsrFxEvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit  = OsrFxEvtDeviceD0Exit;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);

    //
    // Now specify the size of device extension where we track per device
    // context.DeviceInit is completely initialized. So call the framework
    // to create the device and attach it to the lower stack.
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);

    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfDeviceCreate failed with Status code %!STATUS!\n", status);
        return status;
    }

    //
    // Get the DeviceObject context by using accessor function specified in
    // the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro for DEVICE_CONTEXT.
    //
    pDevContext = GetDeviceContext(device);

    //
    // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so
    // that you don't get the popup in usermode (on Win2K) when you surprise
    // remove the device.
    //
    WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);
    pnpCaps.SurpriseRemovalOK = WdfTrue;

    WdfDeviceSetPnpCapabilities(device, &pnpCaps);

    //
    // Create a parallel default queue and register an event callback to
    // receive ioctl requests. We will create separate queues for
    // handling read and write requests. All other requests will be
    // completed with error status automatically by the framework.
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
                             WdfIoQueueDispatchParallel);

    ioQueueConfig.EvtIoDeviceControl    = OsrFxEvtIoDeviceControl;

    status = WdfIoQueueCreate(device,
                             &ioQueueConfig,
                             WDF_NO_OBJECT_ATTRIBUTES,
                             &queue);// pointer to default queue
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                            "WdfIoQueueCreate failed  %!STATUS!\n", status);
        return status;
    }

    //
    // We will create a separate sequential queue and configure it
    // to receive read requests.  We also need to register a EvtIoStop
    // handler so that we can acknowledge requests that are pending
    // at the target driver.
    //
    WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchSequential);

    ioQueueConfig.EvtIoRead = OsrFxEvtIoRead;
    ioQueueConfig.EvtIoStop = OsrFxEvtIoStop;

    status = WdfIoQueueCreate(
                 device,
                 &ioQueueConfig,
                 WDF_NO_OBJECT_ATTRIBUTES,
                 &queue // queue handle
             );

    if (!NT_SUCCESS (status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfIoQueueCreate failed 0x%x\n", status);
        return status;
    }

    status = WdfDeviceConfigureRequestDispatching(
                    device,
                    queue,
                    WdfRequestTypeRead);

    if(!NT_SUCCESS (status)){
        ASSERT(NT_SUCCESS(status));
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfDeviceConfigureRequestDispatching failed 0x%x\n", status);
        return status;
    }


    //
    // We will create another sequential queue and configure it
    // to receive write requests.
    //
    WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchSequential);

    ioQueueConfig.EvtIoWrite = OsrFxEvtIoWrite;
    ioQueueConfig.EvtIoStop  = OsrFxEvtIoStop;

    status = WdfIoQueueCreate(
                 device,
                 &ioQueueConfig,
                 WDF_NO_OBJECT_ATTRIBUTES,
                 &queue // queue handle
             );

    if (!NT_SUCCESS (status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfIoQueueCreate failed 0x%x\n", status);
        return status;
    }

     status = WdfDeviceConfigureRequestDispatching(
                    device,
                    queue,
                    WdfRequestTypeWrite);

    if(!NT_SUCCESS (status)){
        ASSERT(NT_SUCCESS(status));
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfDeviceConfigureRequestDispatching failed 0x%x\n", status);
        return status;
    }

    //
    // Register a manual I/O queue for handling Interrupt Message Read Requests.
    // This queue will be used for storing Requests that need to wait for an
    // interrupt to occur before they can be completed.
    //
    WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchManual);

    //
    // This queue is used for requests that dont directly access the device. The
    // requests in this queue are serviced only when the device is in a fully
    // powered state and sends an interrupt. So we can use a non-power managed
    // queue to park the requests since we dont care whether the device is idle
    // or fully powered up.
    //
    ioQueueConfig.PowerManaged = WdfFalse;

    status = WdfIoQueueCreate(device,
                              &ioQueueConfig,
                              WDF_NO_OBJECT_ATTRIBUTES,
                              &pDevContext->InterruptMsgQueue
                              );

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfIoQueueCreate failed 0x%x\n", status);
        return status;
    }

    //
    // Register a device interface so that app can find our device and talk to it.
    //
    status = WdfDeviceCreateDeviceInterface(device,
                        (LPGUID) &GUID_DEVINTERFACE_OSRUSBFX2,
                        NULL);// Reference String
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                 "WdfDeviceCreateDeviceInterface failed  %!STATUS!\n", status);
        return status;
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- OsrFxEvtDeviceAdd\n");

    return status;
}

NTSTATUS
OsrFxEvtDevicePrepareHardware(
    __in WDFDEVICE    Device,
    __in WDFCMRESLIST ResourceList,
    __in WDFCMRESLIST ResourceListTranslated
    )
/*++

Routine Description:

    In this callback, the driver does whatever is necessary to make the
    hardware ready to use.  In the case of a USB device, this involves
    reading and selecting descriptors.

Arguments:

    Device - handle to a device

Return Value:

    NT status value

--*/
{
    NTSTATUS                            status;
    PDEVICE_CONTEXT                     pDeviceContext;
    WDF_USB_DEVICE_INFORMATION          deviceInfo;
    ULONG                               waitWakeEnable;

    UNREFERENCED_PARAMETER(ResourceList);
    UNREFERENCED_PARAMETER(ResourceListTranslated);

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> EvtDevicePrepareHardware\n");

    pDeviceContext = GetDeviceContext(Device);

    //
    // Create a USB device handle so that we can communicate with the
    // underlying USB stack. The WDFUSBDEVICE handle is used to query,
    // configure, and manage all aspects of the USB device.
    // These aspects include device properties, bus properties,
    // and I/O creation and synchronization. We only create device the first
    // the PrepareHardware is called. If the device is restarted by pnp manager
    // for resource rebalance, we will use the same device handle but then select
    // the interfaces again because the USB stack could reconfigure the device on
    // restart.
    //
    if (pDeviceContext->UsbDevice == NULL) {
        status = WdfUsbTargetDeviceCreate(Device,
                                    WDF_NO_OBJECT_ATTRIBUTES,
                                    &pDeviceContext->UsbDevice);
        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                 "WdfUsbTargetDeviceCreate failed with Status code %!STATUS!\n", status);
            return status;
        }
    }   

    status = SelectInterfaces(Device);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "SelectInterfaces failed 0x%x\n", status);
        return status;
    }

    //
    // Retrieve USBD version information, port driver capabilites and device
    // capabilites such as speed, power, etc.
    //
    WDF_USB_DEVICE_INFORMATION_INIT(&deviceInfo);

    status = WdfUsbTargetDeviceRetrieveInformation(
                                pDeviceContext->UsbDevice,
                                &deviceInfo);
    if (NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "IsDeviceHighSpeed: %s\n",
            (deviceInfo.Traits & WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED) ? "TRUE" : "FALSE");
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                "IsDeviceSelfPowered: %s\n",
        (deviceInfo.Traits & WDF_USB_DEVICE_TRAIT_SELF_POWERED) ? "TRUE" : "FALSE");

    waitWakeEnable = deviceInfo.Traits &
                        WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                        "IsDeviceRemoteWakeable: %s\n",
                        waitWakeEnable ? "TRUE" : "FALSE");

    //
    // Enable wait-wake and idle timeout if the device supports it
    //
    if(waitWakeEnable){
        status = OsrFxSetPowerPolicy(Device);
        if (!NT_SUCCESS (status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                                "OsrFxSetPowerPolicy failed  %!STATUS!\n", status);
            return status;
        }
    }

    status = OsrFxConfigContReaderForInterruptEndPoint(pDeviceContext);

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- EvtDevicePrepareHardware\n");

    return status;
}


NTSTATUS
OsrFxEvtDeviceD0Entry(
    __in  WDFDEVICE Device,
    __in  WDF_POWER_DEVICE_STATE PreviousState
    )
/*++

Routine Description:

    EvtDeviceD0Entry event callback must perform any operations that are
    necessary before the specified device is used.  It will be called every
    time the hardware needs to be (re-)initialized.

    This function is not marked pageable because this function is in the
    device power up path. When a function is marked pagable and the code
    section is paged out, it will generate a page fault which could impact
    the fast resume behavior because the client driver will have to wait
    until the system drivers can service this page fault.

    This function runs at PASSIVE_LEVEL, even though it is not paged.  A
    driver can optionally make this function pageable if DO_POWER_PAGABLE
    is set.  Even if DO_POWER_PAGABLE isn't set, this function still runs
    at PASSIVE_LEVEL.  In this case, though, the function absolutely must
    not do anything that will cause a page fault.

Arguments:

    Device - Handle to a framework device object.

    PreviousState - Device power state which the device was in most recently.
        If the device is being newly started, this will be
        PowerDeviceUnspecified.

Return Value:

    NTSTATUS

--*/
{
    PDEVICE_CONTEXT         pDeviceContext;
    NTSTATUS                status;

    pDeviceContext = GetDeviceContext(Device);

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER,
                "-->OsrFxEvtEvtDeviceD0Entry - coming from %s\n",
                DbgDevicePowerString(PreviousState));

    status = WdfIoTargetStart(WdfUsbTargetPipeGetIoTarget(pDeviceContext->InterruptPipe));

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER, "<--OsrFxEvtEvtDeviceD0Entry\n");

    return status;
}


NTSTATUS
OsrFxEvtDeviceD0Exit(
    __in  WDFDEVICE Device,
    __in  WDF_POWER_DEVICE_STATE TargetState
    )
/*++

Routine Description:

    This routine undoes anything done in EvtDeviceD0Entry.  It is called
    whenever the device leaves the D0 state, which happens when the device is
    stopped, when it is removed, and when it is powered off.

    The device is still in D0 when this callback is invoked, which means that
    the driver can still touch hardware in this routine.


    EvtDeviceD0Exit event callback must perform any operations that are
    necessary before the specified device is moved out of the D0 state.  If the
    driver needs to save hardware state before the device is powered down, then
    that should be done here.

    This function runs at PASSIVE_LEVEL, though it is generally not paged.  A
    driver can optionally make this function pageable if DO_POWER_PAGABLE is set.

    Even if DO_POWER_PAGABLE isn't set, this function still runs at
    PASSIVE_LEVEL.  In this case, though, the function absolutely must not do
    anything that will cause a page fault.

Arguments:

    Device - Handle to a framework device object.

    TargetState - Device power state which the device will be put in once this
        callback is complete.

Return Value:

    Success implies that the device can be used.  Failure will result in the
    device stack being torn down.

--*/
{
    PDEVICE_CONTEXT         pDeviceContext;

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER,
          "-->OsrFxEvtDeviceD0Exit - moving to %s\n",
          DbgDevicePowerString(TargetState));

    pDeviceContext = GetDeviceContext(Device);

    WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(pDeviceContext->InterruptPipe),  

WdfIoTargetCancelSentIo);

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER, "<--OsrFxEvtDeviceD0Exit\n");

    return STATUS_SUCCESS;
}


__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
OsrFxSetPowerPolicy(
    __in WDFDEVICE Device
    )
{
    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
    WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings;
    NTSTATUS    status = STATUS_SUCCESS;

    PAGED_CODE();

    //
    // Init the idle policy structure.
    //
    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleUsbSelectiveSuspend);
    idleSettings.IdleTimeout = 10000; // 10-sec

    status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings);
    if ( !NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfDeviceSetPowerPolicyS0IdlePolicy failed %x\n", status);
        return status;
    }

    //
    // Init wait-wake policy structure.
    //
    WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings);

    status = WdfDeviceAssignSxWakeSettings(Device, &wakeSettings);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfDeviceAssignSxWakeSettings failed %x\n", status);
        return status;
    }

    return status;
}


__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
SelectInterfaces(
    __in WDFDEVICE Device
    )
/*++

Routine Description:

    This helper routine selects the configuration, interface and
    creates a context for every pipe (end point) in that interface.

Arguments:

    Device - Handle to a framework device

Return Value:

    NT status value

--*/
{
    WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams;
    NTSTATUS                            status;
    PDEVICE_CONTEXT                     pDeviceContext;
    WDFUSBPIPE                          pipe;
    WDF_USB_PIPE_INFORMATION            pipeInfo;
    UCHAR                               index;
    UCHAR                               numberConfiguredPipes;

    PAGED_CODE();

    pDeviceContext = GetDeviceContext(Device);

    WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE( &configParams);

    status = WdfUsbTargetDeviceSelectConfig(pDeviceContext->UsbDevice,
                                        WDF_NO_OBJECT_ATTRIBUTES,
                                        &configParams);
    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                        "WdfUsbTargetDeviceSelectConfig failed %!STATUS!\n",
                        status);
        return status;
    }

    pDeviceContext->UsbInterface =
                configParams.Types.SingleInterface.ConfiguredUsbInterface;

    numberConfiguredPipes = configParams.Types.SingleInterface.NumberConfiguredPipes;

    //
    // Get pipe handles
    //
    for(index=0; index < numberConfiguredPipes; index++) {

        WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);

        pipe = WdfUsbInterfaceGetConfiguredPipe(
            pDeviceContext->UsbInterface,
            index, //PipeIndex,
            &pipeInfo
            );
        //
        // Tell the framework that it's okay to read less than
        // MaximumPacketSize
        //
        WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pipe);

        if(WdfUsbPipeTypeInterrupt == pipeInfo.PipeType) {
            TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL,
                    "Interrupt Pipe is 0x%p\n", pipe);
            pDeviceContext->InterruptPipe = pipe;
        }

        if(WdfUsbPipeTypeBulk == pipeInfo.PipeType &&
                WdfUsbTargetPipeIsInEndpoint(pipe)) {
            TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL,
                    "BulkInput Pipe is 0x%p\n", pipe);
            pDeviceContext->BulkReadPipe = pipe;
        }

        if(WdfUsbPipeTypeBulk == pipeInfo.PipeType &&
                WdfUsbTargetPipeIsOutEndpoint(pipe)) {
            TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL,
                    "BulkOutput Pipe is 0x%p\n", pipe);
            pDeviceContext->BulkWritePipe = pipe;
        }

    }

    //
    // If we didn't find all the 3 pipes, fail the start.
    //
    if(!(pDeviceContext->BulkWritePipe
            && pDeviceContext->BulkReadPipe && pDeviceContext->InterruptPipe)) {
        status = STATUS_INVALID_DEVICE_STATE;
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                            "Device is not configured properly %!STATUS!\n",
                            status);

        return status;
    }

    return status;
}


__drv_requiresIRQL(PASSIVE_LEVEL)
PCHAR
DbgDevicePowerString(
    __in WDF_POWER_DEVICE_STATE Type
    )
/*++

Updated Routine Description:
    DbgDevicePowerString does not change in this stage of the function driver.

--*/
{
    switch (Type)
    {
    case WdfPowerDeviceInvalid:
        return "WdfPowerDeviceInvalid";
    case WdfPowerDeviceD0:
        return "WdfPowerDeviceD0";
    case PowerDeviceD1:
        return "WdfPowerDeviceD1";
    case WdfPowerDeviceD2:
        return "WdfPowerDeviceD2";
    case WdfPowerDeviceD3:
        return "WdfPowerDeviceD3";
    case WdfPowerDeviceD3Final:
        return "WdfPowerDeviceD3Final";
    case WdfPowerDevicePrepareForHibernation:
        return "WdfPowerDevicePrepareForHibernation";
    case WdfPowerDeviceMaximum:
        return "PowerDeviceMaximum";
    default:
        return "UnKnown Device Power State";
    }
}

[소스분석] WDF sample source - Osrubsfx2 : driver.c

// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //

// driver.c

// 함수 : DriverEntry(),

             OsrFxEvtDriverContextCleanup(),

             TraceEvents()

// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //


#include <osrusbfx2.h>

#if defined(EVENT_TRACING)
//
// The trace message header (.tmh) file must be included in a source file
// before any WPP macro calls and after defining a WPP_CONTROL_GUIDS
// macro (defined in toaster.h). During the compilation, WPP scans the source
// files for DoTraceMessage() calls and builds a .tmh file which stores a unique
// data GUID for each message, the text resource string for each message,
// and the data types of the variables passed in for each message.  This file
// is automatically generated and used during post-processing.
//

#include "driver.tmh"
#else
ULONG DebugLevel = TRACE_LEVEL_INFORMATION;
ULONG DebugFlag = 0xff;
#endif

#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, OsrFxEvtDriverContextCleanup)
#endif

 

// DriverEntry는 드라이버를 초기화하고,  드라이버가 로드된 후에 시스템으로부터 불려지는 첫번째 루틴이다.

__drv_requiresIRQL(PASSIVE_LEVEL)

NTSTATUS
DriverEntry(
    __in PDRIVER_OBJECT  DriverObject,
    __in PUNICODE_STRING RegistryPath
    )
/*++

Routine Description:

 

Parameters Description:

    DriverObject - represents the instance of the function driver that is loaded
    into memory. DriverEntry must initialize members of DriverObject before it
    returns to the caller. DriverObject is allocated by the system before the
    driver is loaded, and it is released by the system after the system unloads
    the function driver from memory.

    RegistryPath - represents the driver specific path in the Registry.
    The function driver can use the path to store driver related data between
    reboots. The path does not store hardware instance specific data.

Return Value:

    STATUS_SUCCESS if successful,
    STATUS_UNSUCCESSFUL otherwise.

--*/
{
    WDF_DRIVER_CONFIG       config;
    NTSTATUS                status;
    WDF_OBJECT_ATTRIBUTES   attributes;             // object 속성

    //
    // Initialize WPP Tracing
    //

    WPP_INIT_TRACING( DriverObject, RegistryPath );

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
                       "OSRUSBFX2 Driver Sample - Driver Framework Edition.\n");

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
                "Built %s %s\n", __DATE__, __TIME__);

    //
    // Initiialize driver config to control the attributes that
    // are global to the driver. Note that framework by default
    // provides a driver unload routine. If you create any resources
    // in the DriverEntry and want to be cleaned in driver unload,
    // you can override that by manually setting the EvtDriverUnload in the
    // config structure. In general xxx_CONFIG_INIT macros are provided to
    // initialize most commonly used members.
    //

    WDF_DRIVER_CONFIG_INIT(     // WDF_DRIVER_CONFIG 구조체 초기화
        &config,
        OsrFxEvtDeviceAdd      // device.c 함수
        );

    //
    // Register a cleanup callback so that we can call WPP_CLEANUP when
    // the framework driver object is deleted during driver unload.
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.EvtCleanupCallback = OsrFxEvtDriverContextCleanup;

    //
    // Create a framework driver object to represent our driver.
    //

    status = WdfDriverCreate(       // Framework Driver Object 생성
        DriverObject,
        RegistryPath,
        &attributes,  // Driver Object Attributes  이 둘은 생성하고자 하는 object 작동방식을
        &config,          // Driver Config Info         설정하는 파라미터이다.
        WDF_NO_HANDLE // hDriver
        );

    if (!NT_SUCCESS(status)) {

        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
                "WdfDriverCreate failed with status 0x%x\n", status);
        //
        // Cleanup tracing here because DriverContextCleanup will not be called
        // as we have failed to create WDFDRIVER object itself.
        // Please note that if your return failure from DriverEntry after the
        // WDFDRIVER object is created successfully, you don't have to
        // call WPP cleanup because in those cases DriverContextCleanup
        // will be executed when the framework deletes the DriverObject.
        //

        WPP_CLEANUP(DriverObject);
    }

    return status;
}


VOID
OsrFxEvtDriverContextCleanup(
    __in WDFDRIVER Driver
    )
/*++
Routine Description:

    DriverEntry 안에 할당된 리소스를 해제한다.  

Arguments:

    Driver - handle to a WDF Driver object.

Return Value:

    VOID.

--*/
{
    PAGED_CODE ();    // 특정 함수가 IRQL DISPATCH_LEBEL 또는 그 이상의 IRQL 레벨에서 동작하지 않으면

                                      // Assert를 발생해주는 매크로

    UNREFERENCED_PARAMETER(Driver);      // Driver 파라미터를 이 함수에서 참조하지 않는다.

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
                    "--> OsrFxEvtDriverContextCleanup\n");

    WPP_CLEANUP( WdfDriverWdmGetDriverObject( Driver ));

}

#if !defined(EVENT_TRACING)


VOID
TraceEvents (
    __in ULONG DebugPrintLevel,
    __in ULONG DebugPrintFlag,
    __drv_formatString(printf)
    __in PCSTR DebugMessage,
    ...
    )

/*++

Routine Description:

    Debug print for the sample driver.

Arguments:

    TraceEventsLevel - print level between 0 and 3, with 3 the most verbose

Return Value:

    None.

 --*/
 {
#if DBG
#define     TEMP_BUFFER_SIZE        1024
    va_list    list;
    CHAR       debugMessageBuffer[TEMP_BUFFER_SIZE];
    NTSTATUS   status;

    va_start(list, DebugMessage);

    if (DebugMessage) {

        //
        // Using new safe string functions instead of _vsnprintf.
        // This function takes care of NULL terminating if the message
        // is longer than the buffer.
        //

        status = RtlStringCbVPrintfA( debugMessageBuffer,
                                      sizeof(debugMessageBuffer),
                                      DebugMessage,
                                      list );
        if(!NT_SUCCESS(status)) {

            DbgPrint (_DRIVER_NAME_": RtlStringCbVPrintfA failed 0x%x\n", status);
            return;
        }
        if (DebugPrintLevel <= TRACE_LEVEL_ERROR ||
            (DebugPrintLevel <= DebugLevel &&
             ((DebugPrintFlag & DebugFlag) == DebugPrintFlag))) {
            DbgPrint("%s %s", _DRIVER_NAME_, debugMessageBuffer);
        }
    }
    va_end(list);

    return;
#else
    UNREFERENCED_PARAMETER(TraceEventsLevel);
    UNREFERENCED_PARAMETER(TraceEventsFlag);
    UNREFERENCED_PARAMETER(DebugMessage);
#endif
}

#endif