Nerdworks logo "The nerd shall inherit the earth."

Nerdworks Blogorama

Nerdspeak

Turn off VS.NET 2005 deprecation
Technobabble
6/25/2006 3:13:32 PM  

If you've been compiling projects created using earlier versions of VisualStudio in VisualStudio 2005 then you have most certainly noticed the new security warnings that get displayed whenever an in-secure CRT routine is invoked from your code. If you call strcpy for instance, you'd see this:

    warning C4996: 'strcpy' was declared deprecated
    This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use
    _CRT_SECURE_NO_DEPRECATE. See online help for details.

If you're writing new code then it is generally a good idea to listen to this warning and change your code. If you are building an existing project however (an open source project for example) then you're likely to get hundreds of C4996 warnings. One straightforward way of turning them off is to disable deprecation warnings by defining _CRT_SECURE_NO_DEPRECATE.

If you've got a large solution with 15-20 projects and 2-3 build configurations in each then defining this symbol for each project can be one seriously daunting task. In a 10 project solution with each project having a "Debug" and a "Release" configuration for instance you'd have to define this symbol in the project properties dialog 20 times (10 * 2)! I found myself having to do this often enough to warrant the writing of a small VisualStudio macro to do the job. This macro captures the preprocessor definitions from an input box and adds it to all the configurations of each project that is currently selected in the solution explorer. Here's the macro definition:

Public Sub AddPreprocessorMacroToAllProjects()

    '
    ' check whether at least one project has been selected
    '
    If DTE.ActiveSolutionProjects.Length = 0 Then
        MsgBox("Please select the Visual C++ project(s) " + _
            "to which you would like a macro to be added.")
        Exit Sub
    End If

    '
    ' get the macro names and values
    '
retry:
    Dim macro As String
    macro = InputBox("Please enter one or more macros " + _
        "(e.g. _WIN32_WINNT=0x0500; WINVER=0x0500)", _
            "Enter Macros").Trim()
    If macro.Length = 0 Then
        If MsgBox("An empty macro was entered.  Retry?", _
                MsgBoxStyle.YesNo, _
                "Wrong macro") = MsgBoxResult.Yes Then
            GoTo retry
        Else
            Exit Sub
        End If
    End If

    '
    ' now iterate through each project in the array and add the
    ' macro to all the configurations of all visual c++ projects
    '
    Dim i As Integer
    Dim project As Project
    Dim VCProjectKind As String = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}"

    For i = 0 To DTE.ActiveSolutionProjects.Length - 1
        project = DTE.ActiveSolutionProjects(i)

        '
        ' is it a visual c++ project?
        '
        If project.Kind = VCProjectKind Then
            Dim vcproj As Microsoft.VisualStudio.VCProjectEngine.VCProject
            vcproj = project.Object
            Dim j As Integer

            '
            ' iterate through each configuration on this project
            '
            For j = 1 To vcproj.Configurations.Count
                Dim config As Microsoft.VisualStudio.VCProjectEngine.VCConfiguration
                config = vcproj.Configurations(j)

                '
                ' now add the macro to the compiler settings of this configuration
                '
                Dim cl As Microsoft.VisualStudio.VCProjectEngine.VCCLCompilerTool
                cl = config.Tools("VCCLCompilerTool")
                cl.PreprocessorDefinitions = cl.PreprocessorDefinitions + "; " + macro
            Next
        End If
    Next

    MsgBox("Done.")

End Sub

Feel free to use it if you find it useful!

Link Comment
 
NTFS File Streams
Technobabble
6/4/2006 1:19:34 PM  

The Windows NTFS file system has for a long long time included support for what is known as "streams". The idea is to view a file as being a container for 1 or more data streams.  Security information for a file for instance could be stored in stream A and the main file data in stream B.  The interesting thing is that the operating system will directly recognize only data stored in what is known as the default stream.  This default stream is always called $DATA and crud stored in this stream alone is used while accounting for things like file size!  To see streams in action try this out (this will obviously work only if your file system is NTFS):

  • Open a command prompt.
  • Type echo This is in the default stream > ding.txt.
  • Type dir ding.txt. System reports the size as being 32 bytes.
  • Now type echo This is in a hidden stream > ding.txt:bar.
  • Type dir ding.txt. System still reports the size as being 32 bytes.
  • Type more < ding.txt. System prints out This is in the default stream.
  • Now type more < ding.txt:bar. System prints out This is in a hidden stream!

As it turns out, you can specify a stream name along with the file name to deal with specific streams inside a file (ding.txt:bar). Further, for all practical purposes, data stored in non-default streams seem to get ignored by the operating system. While that is so, when you do things like copy/move files from one location to another the system does ensure that it copies the supplementary stream also with it. Now if you're a worm/virus writer I can see you rubbing your hands in glee thinking of all the security implications. But given that this capability has been around since 1993, chances are, all the security folks already know about it!

There's a nice little article on this topic at the following URL. Go take a look!

http://www.osronline.com/article.cfm?article=457
Link Comment (2)
 
What it takes to write 64-bit apps
Technobabble
6/2/2006 6:08:35 PM  

Matt Pietrek has written a nice new article on MSDN about everything that you need to know to get started writing applications for 64-bit versions of Windows - otherwise known as x64. It is available here:

http://msdn.microsoft.com/msdnmag/issues/06/05/x64/default.aspx

For your quick reference (and mine :) I've jotted down the important points here if you haven't got the time or inclination to read the article. Here goes.

  • Moving from 32-bit to 64-bit is not just a re-compile away.
  • You get to address really really large chunks of memory (on the order of terabytes and even larger). Each process gets its own 8TB chunk of memory from the OS.
  • All system DLLs are loaded above 4GB typically at addresses around 0x7FF00000000.
  • The x64 linker assigns the default load address for 64-bit applications to just above 32 bits. This is being done so that you can quickly discover porting bugs. If you are for instance using a 32-bit pointer where you should have used a 64-bit pointer, because the base address is greater than what can be accommodated in 32 bits the pointer will effectively get truncated resulting in an access violation.
  • Most Win32 datatypes continue to retain the size from the 32-bit world. INTs, LONGs, WORDs and DWORDs continue to be 32-bits wide. HANDLEs have become 64-bits wide though.
  • x64 versions of Windows include a sub-system called WOW64 that allows 32-bit applications to just work on x64.
  • A 64-bit application cannot load 32-bit DLLs and vice versa. However 64 and 32-bit applications can still talk to each other using inter-process communication mechanisms (shared memory, named pipes, synchronization objects).
  • x64 is officially off limits for 16-bit applications.
  • Two copies of system DLLs are maintained - one for 64-bit applications and one for 32-bit applications. WOW64 silently re-directs file I/O on the system folder for 32-bit applications to \Windows\SysWow64. If you want to figure out the path to the 32-bit system folder from a 64-bit app then you can do that by calling GetSystemWow64Directory.
  • Just like the file system, WOW64 silently re-directs access to the registry also for 32-bit applications. This is to prevent each type of application from stepping on each other's toes, as can happen when a 64-bit app CoCreateInstances a 32-bit COM component! So, a 32-bit application would see a different HKEY_CLASSES_ROOT (and a few other keys) as opposed to a 64-bit app.
  • x64 now includes a feature called PatchGuard which basically BSODs your system if any kernel mode code alters important kernel mode data structures such as the Interrupt Dispatch Table (IDT). Hmm. Now there's a challenge for rootkit writers and tools such as Regmon that rely on being able to mess around with the IDT.
  • CPU registers are now 64-bits wide (obviously) and are called RAX, RBX, RCX, RDX, RSI and so forth. 8 new general purpose registers have been added and are called R8, R9, R10 and so on till R15.
  • No more __cdecl, __stdcall, __fastcall or __thiscall! There is only a single calling convention in x64 which passes the first 4 parameters to a function via RCX, RDX, R8 and R9 and the remaining parameters via the stack.

A few quick points on writing code that works on 32-bit and 64-bit computers:

  • Pointers cannot be stored in 32-bit types such as ints, longs or DWORDs.
  • Use DWORD_PTRs, INT_PTRs and LONG_PTRs when you want to store pointer values. These types automatically become 64-bits wide on x64 systems (after a recompile that is).
  • When you use functions like printf and sprintf do not use %X to print pointer values. Use %p and you're automagically protected.
  • Inline assembly is not supported in the 64-bit C++ compiler. Boo! hoo!
Link Comment
 
blogorama home
about this blog
email the author
where on earth am i?
subscribe to mailing list
feeds Use these links for feed syndication
rss  |  atom
by category
technobabble (33)
philosophical crud (3)
irrelevant stuff (7)
archive
march, 2009 (2)
august, 2008 (2)
march, 2008 (1)
january, 2008 (1)
september, 2007 (2)
april, 2007 (1)
february, 2007 (2)
december, 2006 (1)
october, 2006 (1)
september, 2006 (4)
august, 2006 (3)
july, 2006 (4)
june, 2006 (3)
may, 2006 (6)
april, 2006 (2)
recent entries
Writing a sensor dr...
Enabling JSONP call...
The Conman
Memoization - Optim...
Random Lisp thought...
Learning Common Lis...
JavaScript closures...
Calling a JavaScrip...
92040 hits