2013年6月29日星期六

IoRegisterDriverReinitialization.C

/*
文本就命名为:IoRegisterDriverReinitialization.C吧!
made by correy
made at 2013.06.29
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com
*/

#include <ntifs.h>

DRIVER_REINITIALIZE Reinitialize;
VOID Reinitialize(__in struct _DRIVER_OBJECT  *DriverObject, __in_opt PVOID  Context, __in ULONG  Count)
{
    //如果是IoRegisterDriverReinitialization注册的,DriverEntry运行之后就走到这里了。
    //如果是IoRegisterBootDriverReinitialization注册的,DriverEntry运行之后不会走到这里,可能在系统启动的某个时候运行。

    /*
    A driver can call this routine only if its DriverEntry routine will return STATUS_SUCCESS.
    If the driver-supplied Reinitialize routine must use the registry,
    the DriverEntry routine should include a copy of the string to which RegistryPath points as part of the context passed to the Reinitialize routine in this call.

    If the driver is loaded dynamically,
    it is possible for this to occur during a normally running system,
    so all references to the reinitialization queue must be synchronized.

    The Count input to a DriverReinitializationRoutine indicates how many times this routine has been called, including the current call.

    The DriverEntry routine can call IoRegisterDriverReinitialization only once.
    If the Reinitialize routine should be run again after any other drivers' Reinitialize routines have returned control,
    the Reinitialize routine also can call IoRegisterDriverReinitialization as many times as the driver's Reinitialize routine should be run.

    Usually, a driver with a Reinitialize routine is a higher-level driver that controls both PnP and legacy devices.
    Such a driver must not only create device objects for the devices that the PnP manager detects (and for which the PnP manager calls the driver's AddDevice routine),
    the driver must also create device objects for legacy devices that the PnP manager does not detect.
    A driver can use a Reinitialize routine to create those device objects and layer the driver over the next-lower driver for the underlying device.
    */

    KdBreakPoint();
}

DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{  

}

#pragma INITCODE
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT  * DriverObject, __in PUNICODE_STRING  RegistryPath)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;

    KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()

    DriverObject->DriverUnload = Unload;      
       
    //IoRegisterBootDriverReinitialization(DriverObject,Reinitialize,0);
    IoRegisterDriverReinitialization(DriverObject,Reinitialize,0);
   
    return STATUS_SUCCESS;
}

2013年6月28日星期五

IShellDispatch2.Cpp

// 本工程的位置在:Microsoft SDKs\Windows\v7.1\Samples\winui\shell\appplatform\ExecInExplorer。

#include <windows.h>
#include <shlwapi.h>
#include <shlobj.h>

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

// use the shell view for the desktop using the shell windows automation to find the desktop web browser and then grabs its view
// returns:IShellView, IFolderView and related interfaces
HRESULT GetShellViewForDesktop(REFIID riid, void **ppv)
{
    *ppv = NULL;

    IShellWindows *psw;
    HRESULT hr = CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&psw));
    if (SUCCEEDED(hr))
    {
        HWND hwnd;
        IDispatch* pdisp;
        VARIANT vEmpty = {}; // VT_EMPTY
        if (S_OK == psw->FindWindowSW(&vEmpty, &vEmpty, SWC_DESKTOP, (long*)&hwnd, SWFO_NEEDDISPATCH, &pdisp))
        {
            IShellBrowser *psb;
            hr = IUnknown_QueryService(pdisp, SID_STopLevelBrowser, IID_PPV_ARGS(&psb));
            if (SUCCEEDED(hr))
            {
                IShellView *psv;
                hr = psb->QueryActiveShellView(&psv);
                if (SUCCEEDED(hr))
                {
                    hr = psv->QueryInterface(riid, ppv);
                    psv->Release();
                }
                psb->Release();
            }
            pdisp->Release();
        } else {
            hr = E_FAIL;
        }
        psw->Release();
    }
    return hr;
}

// From a shell view object gets its automation interface and from that gets the shell application object that implements IShellDispatch2 and related interfaces.
HRESULT GetShellDispatchFromView(IShellView *psv, REFIID riid, void **ppv)
{
    *ppv = NULL;

    IDispatch *pdispBackground;
    HRESULT hr = psv->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&pdispBackground));
    if (SUCCEEDED(hr))
    {
        IShellFolderViewDual *psfvd;
        hr = pdispBackground->QueryInterface(IID_PPV_ARGS(&psfvd));
        if (SUCCEEDED(hr))
        {
            IDispatch *pdisp;
            hr = psfvd->get_Application(&pdisp);
            if (SUCCEEDED(hr))
            {
                hr = pdisp->QueryInterface(riid, ppv);
                pdisp->Release();
            }
            psfvd->Release();
        }
        pdispBackground->Release();
    }
    return hr;
}

HRESULT ShellExecInExplorerProcess(PCWSTR pszFile)
{
    IShellView *psv;
    HRESULT hr = GetShellViewForDesktop(IID_PPV_ARGS(&psv));
    if (SUCCEEDED(hr))
    {
        IShellDispatch2 *psd;
        hr = GetShellDispatchFromView(psv, IID_PPV_ARGS(&psd));
        if (SUCCEEDED(hr))
        {
            BSTR bstrFile = SysAllocString(pszFile);
            hr = bstrFile ? S_OK : E_OUTOFMEMORY;
            if (SUCCEEDED(hr))
            {
                VARIANT vtEmpty = {}; // VT_EMPTY
                hr = psd->ShellExecuteW(bstrFile, vtEmpty, vtEmpty, vtEmpty, vtEmpty);
                SysFreeString(bstrFile);
            }
            psd->Release();
        }
        psv->Release();
    }
    return hr;
}

int WINAPI wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
    HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
    if (SUCCEEDED(hr))
    {
        ShellExecInExplorerProcess(L"c:\\windows\\system32\\calc.exe");//http://www.msn.com
        CoUninitialize();
    }

    MessageBox(0,0,0,0);//测试。

    return 0;
}

IoRegisterShutdownNotification.C

/*
文本就命名为:IoRegisterShutdownNotification.C吧!
made by correy
made at 2013.06.28
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com
*/

#include <ntifs.h>
//#include <ntddk.h> //这两个次序不能乱,有上面的,这个可以注释掉。

DRIVER_DISPATCH DispatchShutdown;
NTSTATUS DispatchShutdown(__in struct _DEVICE_OBJECT  *DeviceObject, __in struct _IRP  *Irp)
{
    /*
    The IoRegisterShutdownNotification routine registers the driver to receive an IRP_MJ_SHUTDOWN IRP for the specified device when the system shuts down.
    The driver receives one such IRP for each device it registers to receive notification for.
    Drivers handle IRP_MJ_SHUTDOWN IRPs within their DispatchShutdown routines.

    If the driver ceases to require shutdown notification for the device,
    use IoUnregisterShutdownNotification to remove the driver from the shutdown notification queue.

    Only one driver in a device stack should register to receive shutdown notification.

    The system sends the driver the IRP_MJ_SHUTDOWN request before it flushes the file systems.
    Some drivers, such as drivers for mass storage devices, can require shutdown notification after the system flushes the file systems.
    To receive shutdown notification for a device after the file systems are flushed, use the IoRegisterLastChanceShutdownNotification routine instead.

    The registered DispatchShutdown routine is called before the power manager sends an IRP_MN_SET_POWER request for PowerSystemShutdown.
    The DispatchShutdown routine is not called for transitions to any other power states.

    A driver writer can make no assumptions about the order in which the driver's DispatchShutdown routine will be called in relation to other such routines or to other shutdown activities.

    A PnP driver might register a shutdown routine to perform certain tasks before system shutdown starts, such as locking down code.

    一下是IoRegisterLastChanceShutdownNotification特有的性质:  

    For any device that is registered with this routine, the system sends the IRP_MJ_SHUTDOWN IRP after all file systems are flushed.
    Only one driver in a device stack should register to receive shutdown notification, by calling either IoRegisterShutdownNotification or IoRegisterLastChanceShutdownNotification.

    A driver that calls IoRegisterLastChanceShutdownNotification must satisfy the following restrictions in its DispatchShutdown routine:
    The DispatchShutdown routine must not call any pageable routines.
    The DispatchShutdown routine must not access pageable memory.
    The DispatchShutdown routine must not perform any file I/O operations.

    Most drivers that require shutdown notification should call the IoRegisterShutdownNotification routine,
    which does not impose these limitations on the DispatchShutdown routine,
    and which causes the DispatchShutdown routine to be called before the file systems are flushed.
    Only drivers that must do some cleanup after the file systems are flushed,
    such as a driver for a mass storage device, should use IoRegisterLastChanceShutdownNotification.  
    */

    KdBreakPoint();

    return 0;
}

DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    PDEVICE_OBJECT DevObj;
    UNICODE_STRING LinkName;  

    DevObj = DriverObject->DeviceObject;
    RtlInitUnicodeString( &LinkName, L"\\DosDevices\\shutdown" );    
    IoDeleteSymbolicLink( &LinkName );// Remove symbolic link from Object namespace...
    IoDeleteDevice( DevObj ); // Unload the callbacks from the kernel to this driver

    IoUnregisterShutdownNotification(DevObj);
}

#pragma INITCODE
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT  * DriverObject, __in PUNICODE_STRING  RegistryPath)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    UNICODE_STRING DeviceName;
    UNICODE_STRING LinkName;
    PDEVICE_OBJECT DeviceObject;

    KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()

    DriverObject->DriverUnload = Unload;  

    /*
    经过测试,如果不注册关机回调,仅仅这一行代码是不起作用的。
                  注册关机回调,没有这一行代码也是不起作用的。
    */
    DriverObject->MajorFunction[ IRP_MJ_SHUTDOWN ] = DispatchShutdown;
       
    RtlInitUnicodeString( &DeviceName, L"\\Device\\shutdown" );  
    status = IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    RtlInitUnicodeString( &LinkName, L"\\DosDevices\\shutdown" );
    status = IoCreateSymbolicLink( &LinkName, &DeviceName );
    if ( !NT_SUCCESS( status )) {
        IoDeleteDevice( DeviceObject );
        return status;
    }
   
    DeviceObject->Flags |= DO_BUFFERED_IO;

    //status = IoRegisterShutdownNotification(DeviceObject);
    status = IoRegisterLastChanceShutdownNotification(DeviceObject);//必须注册设备。方能收到消息。
    if (!NT_SUCCESS(status))
    {
        DbgPrint("IoRegisterShutdownNotification fail!");
        IoDeleteSymbolicLink( &LinkName );// Remove symbolic link from Object namespace...
        IoDeleteDevice( DeviceObject );
    }
   
    return status;//STATUS_SUCCESS
}

2013年6月3日星期一

GetVolumeNameForVolumeMountPoint.Cpp

/*
GetVolumeNameForVolumeMountPoint.Cpp
参考:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365238(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa364037(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365717(v=vs.85).aspx
*/

#include <Windows.h>

#define BUFSIZE MAX_PATH

int MountedFolder( TCHAR * szVolumeMountPoint , TCHAR * szVolumeMountPoint2 )
{
    BOOL bFlag;
    TCHAR Buf[BUFSIZE];     // temporary buffer for volume name

    // We should do some error checking on the inputs. Make sure there
    // are colons and backslashes in the right places, and so on
    bFlag = GetVolumeNameForVolumeMountPoint(
        szVolumeMountPoint2, // input volume mount point or directory
        Buf, // output volume name buffer
        BUFSIZE);  // size of volume name buffer      
    if (bFlag != TRUE) {
        int x = GetLastError();//2 系统找不到指定的文件。
        return (-2);
    }

    //_tprintf( TEXT("Volume name of %s is %s\n"), argv[2], Buf );
    bFlag = SetVolumeMountPoint(
        szVolumeMountPoint, // mount point
        Buf);  // volume to be mounted      
    if (bFlag == 0) {
        int x = GetLastError();
        x = 0;//目录不是空的。 0x00000091 还有0x57 系统找不到指定的文件。
    }

    return (bFlag);
}

void EnumeratingVolumeGUIDPaths()
{
    BOOL bFlag;
    TCHAR Buf[BUFSIZE];           // temporary buffer for volume name
    TCHAR Drive[] = TEXT("c:\\"); // template drive specifier
    TCHAR I;                      // generic loop counter

    // Walk through legal drive letters, skipping floppies.
    for (I = TEXT('c'); I < TEXT('z');  I++ )
    {
        // Stamp the drive for the appropriate letter.
        Drive[0] = I;

        bFlag = GetVolumeNameForVolumeMountPoint(
            Drive,     // input volume mount point or directory
            Buf,       // output volume name buffer
            BUFSIZE ); // size of volume name buffer
        if (bFlag)  {
            _tprintf (TEXT("The ID of drive \"%s\" is \"%s\"\n"), Drive, Buf);
        }
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    //这两个必须存在,不然返回错误。
    wchar_t * path = L"d:\\test\\";//必须为空。
    wchar_t * Volume = L"f:\\";

    int x =  MountedFolder(path , Volume );

    BOOL bFlag = DeleteVolumeMountPoint(path);// Path of the volume mount point

    EnumeratingVolumeGUIDPaths();

    return 0;
}