22 December 2008

Read SD Card CID (serial number)

I just moved blogs, so here's an overview of the SD card CID stuff. I've had some success reading the CID from an SD Card:

Where:

1) The OS is XP or Vista 2) The device is not attached via any USB gizmo. It works only in a card reader attached directly to the PCI bus. (Can scsi pass through get around this? It's not an ATA or SCSI command...) 3) Admin privileges...

What not to do:

1) IOCTL_DISK_GET_STORAGEID 2) GetFileInformationByHandle

As both these return a number assigned when the volume is created. It will change next time the drive is formatted. What I did:

Use IOCTL_SFFDISK_DEVICE_COMMAND to send command 10 (see the SD spec).

Read Secure Digital (SD) Card Serial Number from CID

SD Card Musings

Read CID and CSD C# implementation

Pocket PC?

I don't think it works.

The Future?

IEEE 1667

Paste from Visual studio

0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789

That's using the paste from visual studio plug-in for microsoft's live writer. Tells me the width of this blog. I can then make a guide line appear in the IDE using a registry hack, see

Sarah Ford's weblog - "Guidelines – a hidden feature for the Visual Studio Editor"

(I remember why I didn't use blogger originally -- there's not much room, and I can't be bothered to mess with the templates).

Moving to blogger

I'm sick of Live spaces, as nothing turns up on google searches. Lets see how blogger compares. I'll probably use some of the live spaces facilities such as the file storage...

There will be a brief period of frenzied activity as I move some old posts here.

(Edit: Ok, moved and back dated, which is why this post makes little sense.)

16 December 2008

Determine the layout of a structure for .Net Platform Invoke

I was trying to create a signature for NOTIFYICONDATA, and decided to see what I could find out about it with C++.

1) start a new c++ CLR Console project in visual studio. Name it whatever you like. 2) Alter stdafx.h:

#pragma once
#define STRICT
#include <windows.h>   // common Win32 stuff
#include <commctrl.h>  // defines the structure we are interseted in
#include <stddef.h>    // we use offsetof
using namespace System;  // .Net types

3) in main, you can create a structure and determine its size. You can also find the offset for each field in the structure. Then you can swap the build to x64 and see what size they should be on x64 systems. This is definitely useful for when you want to create a managed C# or VB.Net version of the structure.

#include "stdafx.h"

using namespace System;

int main(array<System::String ^> ^args)
{
    NOTIFYICONDATA tbb;
    int i = sizeof(tbb);
    Console::WriteLine(i);   
    Console::WriteLine(offsetof(NOTIFYICONDATA,cbSize));
    Console::WriteLine(offsetof(NOTIFYICONDATA,hWnd));
    Console::WriteLine(offsetof(NOTIFYICONDATA,uID));
    Console::WriteLine(offsetof(NOTIFYICONDATA,uFlags));
    Console::WriteLine(offsetof(NOTIFYICONDATA,uCallbackMessage));
    Console::WriteLine(offsetof(NOTIFYICONDATA,hIcon));
    Console::WriteLine(offsetof(NOTIFYICONDATA,szTip));
    Console::WriteLine(offsetof(NOTIFYICONDATA,dwState));
    Console::WriteLine(offsetof(NOTIFYICONDATA,dwStateMask));
    Console::WriteLine(offsetof(NOTIFYICONDATA,szInfo));
    Console::WriteLine(offsetof(NOTIFYICONDATA,uTimeout));
    Console::WriteLine(offsetof(NOTIFYICONDATA,szInfoTitle));
    Console::WriteLine(offsetof(NOTIFYICONDATA,dwInfoFlags));
    Console::WriteLine(offsetof(NOTIFYICONDATA,guidItem));
    Console::WriteLine(offsetof(NOTIFYICONDATA,hBalloonIcon));
    Console::ReadKey();
    return 0;
}
Ugly, but it works.

13 December 2008

Open University - story so far

I can never find this:
Open university first class server address: oufcnt2.open.ac.uk This is handy:
My results so far...
(OES/OCAS)
T175 "Networked living: exploring information and communication technologies" - (89/94)
MST121 "Using Mathematics" - (94/92)
M150 "Data, computing and information" - (OCAS 95)
M253 "Team working in distributed environments" - (78/86)
M255 "Object-oriented programming with Java" - (91/96) Distinction M256 "Software development with Java" - (86/95) Distinction M257 "Putting Java to work" - (87/96) Distinction
M263 "Building blocks of software" - (82/97) Distinction M362 "Developing concurrent distributed systems" - (88/95) Distinction
M366 "Natural and Artificial Intelligence" - (93/96) Distinction

Starting early 2009: M359 "Relational databases: theory and practice" M363 "Software engineering with objects" M450 "The computing project"

10 December 2008

VB.Net Global keyboard hook to detect "print screen" keypress

As described...

Option Strict On
Option Explicit On

Imports System.Runtime.InteropServices

Public Class Form1

    Private Const WH_KEYBOARD_LL As Integer = 13
    Private Const WM_KEYUP As Integer = &H101
    Private Const WM_SYSKEYUP As Integer = &H105
    Private proc As LowLevelKeyboardProcDelegate = AddressOf HookCallback
    Private hookID As IntPtr

    Private Delegate Function LowLevelKeyboardProcDelegate(ByVal nCode As Integer, ByVal wParam As IntPtr, _
        ByVal lParam As IntPtr) As IntPtr

    <DllImport("user32")> _
    Private Shared Function SetWindowsHookEx(ByVal idHook As Integer, ByVal lpfn As LowLevelKeyboardProcDelegate, _
        ByVal hMod As IntPtr, ByVal dwThreadId As UInteger) As IntPtr
    End Function

    <DllImport("user32.dll")> _
    Private Shared Function UnhookWindowsHookEx(ByVal hhk As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function

    <DllImport("user32.dll")> _
    Private Shared Function CallNextHookEx(ByVal hhk As IntPtr, ByVal nCode As Integer, ByVal wParam As IntPtr, _
        ByVal lParam As IntPtr) As IntPtr
    End Function

    <DllImport("kernel32.dll", CharSet:=CharSet.Unicode)> _
    Private Shared Function GetModuleHandle(ByVal lpModuleName As String) As IntPtr
    End Function

    Sub New()
        ' This call is required by the Windows Form Designer.
        InitializeComponent()
        ' Add any initialization after the InitializeComponent() call.
        hookID = SetHook(proc)
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs) Handles Me.FormClosing
        UnhookWindowsHookEx(hookID)
    End Sub

    Private Function SetHook(ByVal proc As LowLevelKeyboardProcDelegate) As IntPtr
        Using curProcess As Process = Process.GetCurrentProcess()
            Using curModule As ProcessModule = curProcess.MainModule
                Return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0)
            End Using
        End Using
    End Function

    Private Function HookCallback(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
        ' we check keyup for standard printscreen, and syskeyup incase it is alt+printscreen
        ' we aren't checking keydown, as that fires before the screenshot is taken.
        If nCode >= 0 AndAlso (wParam.ToInt32 = WM_KEYUP OrElse wParam.ToInt32 = WM_SYSKEYUP) Then
            Dim vkCode As Integer = Marshal.ReadInt32(lParam)
            If vkCode = Keys.PrintScreen Then
                Dim data As IDataObject = Clipboard.GetDataObject()
                If data.GetDataPresent(GetType(Bitmap)) Then
                    Me.BackgroundImage = DirectCast(data.GetData(GetType(Bitmap)), Bitmap)
                End If
            End If
        End If
        Return CallNextHookEx(hookID, nCode, wParam, lParam)
    End Function

End Class

SetClipboardViewer API VB.NET

This registers a form as a clipboard viewer. It then recieves notification when something happens to the clipboard. Some post on the msdn forum. It mentioned: http://www.radsoftware.com.au/articles/ClipboardMonitor_VB.txt, which I've tidied up to my liking (a stray long, a strange cast removed, you can't override Dispose (could you before?))
Option Strict On
Option Explicit On

Imports System.Runtime.InteropServices

Public Class Form1

   Private Const WM_DRAWCLIPBOARD As Integer = &H308
   Private Const WM_CHANGECBCHAIN As Integer = &H30D

   Private mNextClipBoardViewerHWnd As IntPtr
   Private Event OnClipboardChanged()

   <DllImport("user32")> _
   Private Shared Function SetClipboardViewer(ByVal hWnd As IntPtr) As IntPtr
   End Function

   <DllImport("user32")> _
   Private Shared Function ChangeClipboardChain(ByVal hWnd As IntPtr, ByVal hWndNext As IntPtr) As _
       <MarshalAs(UnmanagedType.Bool)> Boolean
   End Function

   <DllImport("user32")> _
   Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, _
       ByVal lParam As IntPtr) As IntPtr
   End Function

   Sub New()
       InitializeComponent()
       mNextClipBoardViewerHWnd = SetClipboardViewer(Me.Handle)
       AddHandler Me.OnClipboardChanged, AddressOf ClipBoardChanged
   End Sub

   Protected Overrides Sub WndProc(ByRef m As Message)
       Select Case m.Msg
           Case WM_DRAWCLIPBOARD
               RaiseEvent OnClipboardChanged()
               SendMessage(mNextClipBoardViewerHWnd, m.Msg, m.WParam, m.LParam)

           Case WM_CHANGECBCHAIN
               If m.WParam.Equals(mNextClipBoardViewerHWnd) Then
                   mNextClipBoardViewerHWnd = m.LParam
               Else
                   SendMessage(mNextClipBoardViewerHWnd, m.Msg, m.WParam, m.LParam)
               End If
       End Select
       MyBase.WndProc(m)
   End Sub

   Private Sub ClipBoardChanged()
       Dim data As IDataObject = Clipboard.GetDataObject()
       If data.GetDataPresent(GetType(Bitmap)) Then
           Me.BackgroundImage = DirectCast(data.GetData(GetType(Bitmap)), Bitmap)
       End If
   End Sub

   Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs) Handles Me.FormClosing
       ChangeClipboardChain(Me.Handle, mNextClipBoardViewerHWnd)
   End Sub

End Class

To use: start a few instances of the program. Copy an image into the clipboard - the backgrounds of the forms should change. Then close one of the forms and change the image in the clipboard - all the backgrounds should change.