views:

461

answers:

2

I'm currently trying to run the NdisProt driver given by WinDDK 2003. I've build and installed the driver successfully.

It comes with a test utility named uiotest

When I build the utility with make it runs correctly.

When I create a blank win32 application solution with Visual Studio 2005 it cannot connect to the driver during CreateFile( "\\.\\NdisProt" [...])`. The call always returns an invalid handle. I suspect that my project is not built exactly the same as with make. Here is the content of the "sources" file used by make

TARGETNAME=uiotest
TARGETPATH=obj
TARGETTYPE=PROGRAM

C_DEFINES=$(C_DEFINES) -D_WIN32WIN_

# MSC_WARNING_LEVEL=/W4

UMTYPE=console
USE_MSVCRT=1

TARGETLIBS=\
    $(SDK_LIB_PATH)\user32.lib

INCLUDES=..\sys

SOURCES=\
    uiotest.c

I've added the lib path and include path to my project

here is what make returns from the ddk environement

cl -nologo -Ii386\ -I. -ID:\WINDDK\3790~1.183\inc\mfc42 -I..\sys -Iobjfre_wxp_x8
6\i386 -ID:\WINDDK\3790~1.183\inc\wxp -ID:\WINDDK\3790~1.183\inc\wxp -ID:\WINDDK
\3790~1.183\inc\crt -D_X86_=1 -Di386=1  -DSTD_CALL -DCONDITION_HANDLING=1   -DNT
_INST=0 -DWIN32=100 -D_NT1X_=100 -DWINNT=1 -D_WIN32_WINNT=0x0501 /DWINVER=0x0501
 -D_WIN32_IE=0x0603    -DWIN32_LEAN_AND_MEAN=1 -DDEVL=1 -D__BUILDMACHINE__=WinDD
K -DFPO=0  -DNDEBUG -D_DLL=1 -D_MT=1  -D_WIN32WIN_     /c /Zl /Zp8 /Gy /Gm-  /W3
 /WX /Gz  /GX-  /GR- /GF /GS /G6 /Ze /Gi- /QIfdiv- /hotpatch -Z7 /Oxs  /Oy-   -F
ID:\WINDDK\3790~1.183\inc\wxp\warning.h   .\uiotest.c
uiotest.c
        link -out:objfre_wxp_x86\i386\uiotest.exe -machine:ix86 @C:\Temp\nm88BE.
tmp
Microsoft (R) Incremental Linker Version 7.10.4035
Copyright (C) Microsoft Corporation.  All rights reserved.

-MERGE:_PAGE=PAGE
-MERGE:_TEXT=.text
-SECTION:INIT,d
-OPT:REF
-OPT:ICF
-IGNORE:4198,4010,4037,4039,4065,4070,4078,4087,4089,4221
-INCREMENTAL:NO
-FULLBUILD
/release
-NODEFAULTLIB
/WX
-debug
-debugtype:cv
-version:5.1
-osversion:5.1
/functionpadmin:5
/safeseh
/opt:nowin98
-merge:.rdata=.text
/pdbcompress
-STACK:0x40000,0x2000
/tsaware
-subsystem:console,4.00
-base:@D:\WINDDK\3790~1.183\bin\coffbase.txt,usermode
-entry:mainCRTStartup
objfre_wxp_x86\i386\uiotest.obj
D:\WINDDK\3790~1.183\lib\wxp\i386\BufferOverflowU.lib
D:\WINDDK\3790~1.183\lib\crt\i386\msvcrt.lib
D:\WINDDK\3790~1.183\lib\wxp\i386\advapi32.lib
D:\WINDDK\3790~1.183\lib\wxp\i386\kernel32.lib
D:\WINDDK\3790~1.183\lib\wxp\i386\user32.lib
D:\WINDDK\3790~1.183\lib\wxp\i386\sehupd.lib

I'm not too sure about what to check to know what's going on so any help would be appreciable. The new project compiles and run, but the CreateFile() fails with INVALID_HANDLE_VALUE

+3  A: 

It may not be the whole problem, but one thing that leaps out from the code quoted is the call CreateFile("\\.\\NdisProt",...). The correct path name of an object in the kernel name space begins with two backslashes, each of which needs to be doubled in a C string. I've had problems with the markup language used at SO being confused by backslashes in the past, so I took the liberty of editing your question to make sure I was seeing the name you intended to present, and to fix the markup to preserve that intent.

So, the name used to create a handle to the device object should look like

CreateFile("\\\\.\\NdisProt",...)

to address the device object named

\\.\NdisProt

I have no idea if there are any other issues, or even if that is the correct name exported by that driver.

The DDK samples are generally written to be free of dependencies on things like MFC, ATL, WTL, and the like. This results in a kind of stilted style in the code, but it has the benefit that the samples can be built with the tool chain that originally shipped with the DDK itself and are relatively independent of the choice of toolchain used.

Note that if you end up trying to really debug a driver, you might need to track a call from the user mode code through the kernel and into the relevant bits of the driver. Doing that with the kernel debugger is easier if the user mode code is as simple as possible. This might also explain the style used in the sample code.

Edit: If there is also a Unicode vs. ANSI issue floating, then you should review your code for places where narrow strings are passed to APIs that expect wide strings and fix them.

One fix that is easy would be to switch to an ANSI compile for all Windows APIs. Of course, now you have problems with file names that include national characters not in your current code page since there is no way to guarantee that the Unicode file name can be correctly translated to and from ANSI.

One fix that might be "good enough" is to make string constants wide by writing them L"...". However, now your code is guaranteed not to be portable back to an ANSI compile, so be sure to use a compile-time assertion to verify that UNICODE is defined so that you get a good error message then.

The party line at Microsoft seems to be to never use either char or wchar_t but to instead use TCHAR. The header <tchar.h> supplies mapping macros that allow strings to be declared and used in the Windows API and in the C runtime libraries by choosing the wide or narrow API at compile time. Arguably, this is the correct thing to do in a Windows application since it is already not very portable to other platforms.

However, getting the macro magic right to deal with translating TCHARs to a known representation is a pain.

Regardless of which technique you choose, I don't see any way out of doing a careful and complete code review for string handling and character representation assumptions.

RBerteig
A: 

Half soved :

CreateFile is referencing CreateFileW which waits for a unicode string. When I force CreateFileA it works.

Eric
Passing a narrow string to CreateFileW would probably generate a compiler warning when you compile the program. What other compiler warnings are you not telling us about?
bk1e