Category: English


Some days ago my new HC-SR04 ultrasonic sensor for my new Arduino board arrived. In order to keep the overview of my programs, I have written a small library for the sensor which I want to share with you here. As the library is pretty much self-explicatory in my opinion, I will not further comment the following code at this point.

UltraSonic.h

/*
  UltraSonic.h - A library for the HC-SR04 UltraSonic sensor.
  Created by Birk Blechschmidt, May 25, 2013.
  Released into the public domain.
*/

#ifndef UltraSonic_h
	#define UltraSonic_h

	#include "Arduino.h"

	class UltraSonic
	{
	  public:
		byte TriggerPin, DataPin;
		UltraSonic(byte TriggerPort, byte DataPort, unsigned int MaximumRange = 400);
		unsigned int ReadCentimeters();
		void ReadCentimetersAsync(int &Centimeters);
	  private:
		unsigned long AsyncTime;
		byte AsyncState;
		unsigned long AsyncLength;
		unsigned int Timeout;
	};

#endif

UltraSonic.cpp

/*
  UltraSonic.cpp - A library for the HC-SR04 UltraSonic sensor.
  Created by Birk Blechschmidt, May 25, 2013.
  Released into the public domain.
*/

#include "Arduino.h"
#include "UltraSonic.h"

UltraSonic::UltraSonic(byte TriggerPort, byte DataPort, unsigned int MaximumRange)
{
  Timeout = MaximumRange * 58;
  TriggerPin = TriggerPort;
  DataPin = DataPort;
  pinMode(TriggerPin, OUTPUT);
  digitalWrite(TriggerPin, LOW);
  pinMode(DataPin, INPUT);
  AsyncState = 0;
}

unsigned int UltraSonic::ReadCentimeters()
{
      digitalWrite(TriggerPin, HIGH);
      delayMicroseconds(10);
      digitalWrite(TriggerPin, LOW);
      return pulseIn(DataPin, HIGH, Timeout)/58;
}

void UltraSonic::ReadCentimetersAsync(int &Centimeters)
{
  switch(AsyncState)
  {
    case 0:
    {
      Centimeters = -1;
      digitalWrite(TriggerPin, HIGH);
      AsyncTime = micros();
      AsyncState++;
      break;
    }
    case 1:
    {
      if(micros() >= AsyncTime + 10)
      {
        AsyncState++;
        digitalWrite(TriggerPin, LOW);
        AsyncTime = micros();
      }
      break;
    }
    case 2:
    {
      if(digitalRead(DataPin) == HIGH)
      {
        AsyncState++;
        AsyncTime = micros();
        
      }
      else if(micros() - AsyncTime > Timeout)
      {
        Centimeters = 0;
        AsyncState = 4; 
      }
      break;
    }
    case 3:
    {
      if(digitalRead(DataPin) == LOW)
      {
        Centimeters = (micros() - AsyncTime) / 58;
        AsyncState++;
      }
      else if(micros() - AsyncTime > Timeout)
      {
        Centimeters = 0;
        AsyncState++;
      }
      break;
    }
    case 4:
    {
      Centimeters = -1;
      AsyncState = 0;
      break;
    }
  }
}

Copy the above files to your Arduino libraries located at C:\Program Files\Arduino\libraries. Please be aware that you might need to create a new folder.

Dear reader,

in this article I will show you how to write an application for downloading videos from the online platform YouTube using any programming language like C# .Net, JavaScript or any other language. I think this topic is quite interesting because I implemented a download function in my YouTube Gadget and I did not find any helpful resources on the internet.

Let’s imagine following situation: You found

a cool video on YouTube, now you want to download it (for playing it on your PC, mobile phone or iPod…).
What we do have is the URL of the YouTube interface similar to “http://www.youtube.com/watch?v=M1wbceaOwfg” containing the swf-file that plays our video.
What we do not have is the URL of the video file our browser is loading. I used Firebug, a useful extension for developers, to get the video file.

Firebug - Getting the video URL

As you can see, I activated the “Netzwerk/Network” module and selected “Flash” contents. You notice that the request which is shown is the request for the video because of the “Content-Type” field of the response header (“Antwort-Header”) which is set to “video/x-flv”, the mimetype of flv-flash-videos. If you copy the requested URL to the address bar of our browser,  a download dialog will be shown and ask you to open or save “videoplayback”. Well, if this file is opened with Adobe Media Player or any other program being able to play flv-videos, you will see that you can watch the downloaded video.

I think this is clear, but more interesting is to automate this process and to download/convert the videos to a more common format. Which mobile phone or iPod can play flv-files? So the next step to do is to search the source code of the YouTube video page for our urls. And – to put it in a nutshell – it can be found in the flashvars of the embed-tag or the object (using Firefox, YouTube’s sourcecode is using an embed-tag while YouTube’s sourcecode for Internet Explorer is using an object-tag).
And this is the quite long code my sourcecode contains:

<embed type="application/x-shockwave-flash"     src="http://s.ytimg.com/yt/swfbin/watch_as3-vfl3Eh29q.swf"     width="640" id="movie_player" height="390"    flashvars="fexp=903104%2C907702&amp;url_encoded_fmt_stream_map=url%3Dhttp%253A%252F%252Fo-o.preferred.fra02s03.v11.lscache4.c.youtube.com%252Fvideoplayback%253Fsparams%253Did%25252Cexpire%25252Cip%25252Cipbits%25252Citag%25252Cratebypass%25252Ccp%2526fexp%253D903104%25252C907702%2526itag%253D43%2526ip%253D87.0.0.0%2526signature%253D30417352A65E14163FB6746AE6C6A871517A5FC9.0C91E36B690A5C885AAE0B7F43FE564444C00AD0%2526sver%253D3%2526ratebypass%253Dyes%2526expire%253D1317600000%2526key%253Dyt1%2526ipbits%253D8%2526cp%253DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%2526id%253D335c1b71e68ec1f8%26quality%3Dmedium%26fallback_host%3Dtc.v11.cache4.c.youtube.com%26type%3Dvideo%252Fwebm%253B%2Bcodecs%253D%2522vp8.0%252C%2Bvorbis%2522%26itag%3D43%2Curl%3Dhttp%253A%252F%252Fo-o.preferred.fra02s03.v21.lscache2.c.youtube.com%252Fvideoplayback%253Fsparams%253Did%25252Cexpire%25252Cip%25252Cipbits%25252Citag%25252Calgorithm%25252Cburst%25252Cfactor%25252Ccp%2526fexp%253D903104%25252C907702%2526algorithm%253Dthrottle-factor%2526itag%253D34%2526ip%253D87.0.0.0%2526burst%253D40%2526sver%253D3%2526signature%253DBC4BD5E7A48929985F533325AE046E5812B24D45.E599953DFB49361BD0CCDAE3A1FD06C4C7ED5A%2526expire%253D1317600000%2526key%253Dyt1%2526ipbits%253D8%2526factor%253D1.25%2526cp%253DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%2526id%253D335c1b71e68ec1f8%26quality%3Dmedium%26fallback_host%3Dtc.v21.cache2.c.youtube.com%26type%3Dvideo%252Fx-flv%26itag%3D34%2Curl%3Dhttp%253A%252F%252Fo-o.preferred.fra02s03.v22.lscache3.c.youtube.com%252Fvideoplayback%253Fsparams%253Did%25252Cexpire%25252Cip%25252Cipbits%25252Citag%25252Cratebypass%25252Ccp%2526fexp%253D903104%25252C907702%2526itag%253D18%2526ip%253D87.0.0.0%2526signature%253D81FDB64A4A19D55942C6C05CE4752A209C75C00D.D45F795019B8E8214EA20037660EF2B534C817F7%2526sver%253D3%2526ratebypass%253Dyes%2526expire%253D1317600000%2526key%253Dyt1%2526ipbits%253D8%2526cp%253DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%2526id%253D335c1b71e68ec1f8%26quality%3Dmedium%26fallback_host%3Dtc.v22.cache3.c.youtube.com%26type%3Dvideo%252Fmp4%253B%2Bcodecs%253D%2522avc1.42001E%252C%2Bmp4a.40.2%2522%26itag%3D18%2Curl%3Dhttp%253A%252F%252Fo-o.preferred.fra02s03.v22.lscache3.c.youtube.com%252Fvideoplayback%253Fsparams%253Did%25252Cexpire%25252Cip%25252Cipbits%25252Citag%25252Calgorithm%25252Cburst%25252Cfactor%25252Ccp%2526fexp%253D903104%25252C907702%2526algorithm%253Dthrottle-factor%2526itag%253D5%2526ip%253D87.0.0.0%2526burst%253D40%2526sver%253D3%2526signature%253DAB1BAAB6AEB36AA5449436B3B70DAEAC6CF4A309.BFF1F8A5C9179CF25B9121968EA70A0A31DE0088%2526expire%253D1317600000%2526key%253Dyt1%2526ipbits%253D8%2526factor%253D1.25%2526cp%253DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%2526id%253D335c1b71e68ec1f8%26quality%3Dsmall%26fallback_host%3Dtc.v22.cache3.c.youtube.com%26type%3Dvideo%252Fx-flv%26itag%3D5&amp;enablecsi=1&amp;watermark=http%3A%2F%2Fs.ytimg.com%2Fyt%2Fswf%2Flogo-vfl_bP6ud.swf%2Chttp%3A%2F%2Fs.ytimg.com%2Fyt%2Fswf%2Fhdlogo-vfloR6wva.swf&amp;timestamp=1317576346&amp;plid=AASuVCYX1Hr0FlbH&amp;allow_embed=1&amp;watch_ajax_token=CzZGESebg7W8TR9XdtjYvm5lj4J8MTMxNzY2Mjc0NkAxMzE3NTc2MzQ2&amp;vq=auto&amp;showpopout=1&amp;autohide=2&amp;hl=en_US&amp;csi_page_type=watch5&amp;keywords=music%2Cyoutube%2Cgadget%2Cprogram%2Capp%2Capplication%2Csoftware%2Cwindows%2Cvista%2Cplayer%2Cplaylists%2Clisten%2Csidebar%2Cdesktop%2Cwidgets%2Centertainment%2Ccomputer&amp;cr=DE&amp;rvs=view_count%3D407%26author%3DRoboFan1406%26length_seconds%3D%2528104%252C%2529%26id%3D8q9RJ1wZQ5E%26title%3DLord%2Bof%2Bthe%2BRings%2B-%2BLord%2Bof%2Bthe%2BRings%2B-%2BShire%2BMusic%2Cview_count%3D162%26author%3DRoboFan1406%26length_seconds%3D%2528168%252C%2529%26id%3DyXnxYgUA2IA%26title%3DClimbing%2BNXT%2Cview_count%3D288%26author%3DRoboFan1406%26length_seconds%3D%2528109%252C%2529%26id%3DTRtIuqiBh50%26title%3DLEGO%2BMindstorms%2BNXT%2BGabelstapler%2Cview_count%3D4318143%26author%3DElektraRecords%26length_seconds%3D%2528257%252C%2529%26id%3Dfwr1hm_oBxE%26title%3DBruno%2BMars%2B-%2BIt%2BWill%2BRain%2B%255BNew%2BMusic%255D%2Cview_count%3D2724048%26author%3DkellyclarksonVEVO%26length_seconds%3D%2528235%252C%2529%26id%3D0C_oNMH0GTk%26title%3DKelly%2BClarkson%2B-%2BMr.%2BKnow%2BIt%2BAll%2Cview_count%3D2980984%26author%3DSMTOWN%26length_seconds%3D%2528203%252C%2529%26id%3DGvTaLTTanJc%26title%3DSuper%2BJunior%2B%25EC%258A%2588%25ED%258D%25BC%25EC%25A3%25BC%25EB%258B%2588%25EC%2596%25B4_A-CHA_Music%2BVideo%2Cview_count%3D1815682%26author%3DYourfavoritemartian%26length_seconds%3D%2528209%252C%2529%26id%3DTUmJDVRDRTQ%26title%3DWHIP%2BYO%2BKIDS%2Bfeaturing%2BNice%2BPeter%2Cview_count%3D953666%26author%3Drecklessswaggg%26length_seconds%3D%2528241%252C%2529%26id%3DPQocCi6j_mk%26title%3DHOW%2BTO%2BLOVE%2B%2528REMIX%2529%2B-%2BJUSTIN%2BBIEBER&amp;endscreen_module=http%3A%2F%2Fs.ytimg.com%2Fyt%2Fswfbin%2Fendscreen-vflNhEga_.swf&amp;fmt_list=43%2F320x240%2F99%2F0%2F0%2C34%2F320x240%2F9%2F0%2F115%2C18%2F320x240%2F9%2F0%2F115%2C5%2F320x240%2F7%2F0%2F0&amp;referrer=None&amp;user_gender=m&amp;logwatch=1&amp;length_seconds=25&amp;sendtmp=1&amp;enablejsapi=1&amp;sk=764YjHpjrC6O1ctvYaH35ppV7Bd9b6mnR&amp;theme=dark&amp;t=vjVQa1PpcFM-sb-PCui5mX1jKwIXdE1yWObSxWPQFp8%3D&amp;video_id=M1wbceaOwfg&amp;p_w=P-KpDhgwPVs&amp;tk=SVN8E4f4bLdCNRlCrLgJIJlnzby7tCDb5dJjT08JFAX6-DLCnnC5rQ%3D%3D&amp;user_age=33"     allowscriptaccess="always" allowfullscreen="true" bgcolor="#000000">

To make our flashvars more readable and accessible I decrypted the html-entities: (The following only shows the decoded flash parameters/flashvars, the other code is not too interesting.)

fexp=903104%2C907702
&url_encoded_fmt_stream_map=url%3Dhttp%253A%252F%252Fo-o.preferred.fra02s03.v11.lscache4.c.youtube.com%252Fvideoplayback%253Fsparams%253Did%25252Cexpire%25252Cip%25252Cipbits%25252Citag%25252Cratebypass%25252Ccp%2526fexp%253D903104%25252C907702%2526itag%253D43%2526ip%253D87.0.0.0%2526signature%253D30417352A65E14163FB6746AE6C6A871517A5FC9.0C91E36B690A5C885AAE0B7F43FE564444C00AD0%2526sver%253D3%2526ratebypass%253Dyes%2526expire%253D1317600000%2526key%253Dyt1%2526ipbits%253D8%2526cp%253DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%2526id%253D335c1b71e68ec1f8%26quality%3Dmedium%26fallback_host%3Dtc.v11.cache4.c.youtube.com%26type%3Dvideo%252Fwebm%253B%2Bcodecs%253D%2522vp8.0%252C%2Bvorbis%2522%26itag%3D43%2Curl%3Dhttp%253A%252F%252Fo-o.preferred.fra02s03.v21.lscache2.c.youtube.com%252Fvideoplayback%253Fsparams%253Did%25252Cexpire%25252Cip%25252Cipbits%25252Citag%25252Calgorithm%25252Cburst%25252Cfactor%25252Ccp%2526fexp%253D903104%25252C907702%2526algorithm%253Dthrottle-factor%2526itag%253D34%2526ip%253D87.0.0.0%2526burst%253D40%2526sver%253D3%2526signature%253DBC4BD5E7A48929985F533325AE046E5812B24D45.E599953DFB49361BD0CCDAE3A1FD06C4C7ED5A%2526expire%253D1317600000%2526key%253Dyt1%2526ipbits%253D8%2526factor%253D1.25%2526cp%253DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%2526id%253D335c1b71e68ec1f8%26quality%3Dmedium%26fallback_host%3Dtc.v21.cache2.c.youtube.com%26type%3Dvideo%252Fx-flv%26itag%3D34%2Curl%3Dhttp%253A%252F%252Fo-o.preferred.fra02s03.v22.lscache3.c.youtube.com%252Fvideoplayback%253Fsparams%253Did%25252Cexpire%25252Cip%25252Cipbits%25252Citag%25252Cratebypass%25252Ccp%2526fexp%253D903104%25252C907702%2526itag%253D18%2526ip%253D87.0.0.0%2526signature%253D81FDB64A4A19D55942C6C05CE4752A209C75C00D.D45F795019B8E8214EA20037660EF2B534C817F7%2526sver%253D3%2526ratebypass%253Dyes%2526expire%253D1317600000%2526key%253Dyt1%2526ipbits%253D8%2526cp%253DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%2526id%253D335c1b71e68ec1f8%26quality%3Dmedium%26fallback_host%3Dtc.v22.cache3.c.youtube.com%26type%3Dvideo%252Fmp4%253B%2Bcodecs%253D%2522avc1.42001E%252C%2Bmp4a.40.2%2522%26itag%3D18%2Curl%3Dhttp%253A%252F%252Fo-o.preferred.fra02s03.v22.lscache3.c.youtube.com%252Fvideoplayback%253Fsparams%253Did%25252Cexpire%25252Cip%25252Cipbits%25252Citag%25252Calgorithm%25252Cburst%25252Cfactor%25252Ccp%2526fexp%253D903104%25252C907702%2526algorithm%253Dthrottle-factor%2526itag%253D5%2526ip%253D87.0.0.0%2526burst%253D40%2526sver%253D3%2526signature%253DAB1BAAB6AEB36AA5449436B3B70DAEAC6CF4A309.BFF1F8A5C9179CF25B9121968EA70A0A31DE0088%2526expire%253D1317600000%2526key%253Dyt1%2526ipbits%253D8%2526factor%253D1.25%2526cp%253DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%2526id%253D335c1b71e68ec1f8%26quality%3Dsmall%26fallback_host%3Dtc.v22.cache3.c.youtube.com%26type%3Dvideo%252Fx-flv%26itag%3D5
&enablecsi=1
&watermark=http%3A%2F%2Fs.ytimg.com%2Fyt%2Fswf%2Flogo-vfl_bP6ud.swf%2Chttp%3A%2F%2Fs.ytimg.com%2Fyt%2Fswf%2Fhdlogo-vfloR6wva.swf
&timestamp=1317576346
&plid=AASuVCYX1Hr0FlbH
&allow_embed=1
&watch_ajax_token=CzZGESebg7W8TR9XdtjYvm5lj4J8MTMxNzY2Mjc0NkAxMzE3NTc2MzQ2
&vq=auto
&showpopout=1
&autohide=2
&hl=en_US
&csi_page_type=watch5
&keywords=music%2Cyoutube%2Cgadget%2Cprogram%2Capp%2Capplication%2Csoftware%2Cwindows%2Cvista%2Cplayer%2Cplaylists%2Clisten%2Csidebar%2Cdesktop%2Cwidgets%2Centertainment%2Ccomputer
&cr=DE
&rvs=view_count%3D407%26author%3DRoboFan1406%26length_seconds%3D%2528104%252C%2529%26id%3D8q9RJ1wZQ5E%26title%3DLord%2Bof%2Bthe%2BRings%2B-%2BLord%2Bof%2Bthe%2BRings%2B-%2BShire%2BMusic%2Cview_count%3D162%26author%3DRoboFan1406%26length_seconds%3D%2528168%252C%2529%26id%3DyXnxYgUA2IA%26title%3DClimbing%2BNXT%2Cview_count%3D288%26author%3DRoboFan1406%26length_seconds%3D%2528109%252C%2529%26id%3DTRtIuqiBh50%26title%3DLEGO%2BMindstorms%2BNXT%2BGabelstapler%2Cview_count%3D4318143%26author%3DElektraRecords%26length_seconds%3D%2528257%252C%2529%26id%3Dfwr1hm_oBxE%26title%3DBruno%2BMars%2B-%2BIt%2BWill%2BRain%2B%255BNew%2BMusic%255D%2Cview_count%3D2724048%26author%3DkellyclarksonVEVO%26length_seconds%3D%2528235%252C%2529%26id%3D0C_oNMH0GTk%26title%3DKelly%2BClarkson%2B-%2BMr.%2BKnow%2BIt%2BAll%2Cview_count%3D2980984%26author%3DSMTOWN%26length_seconds%3D%2528203%252C%2529%26id%3DGvTaLTTanJc%26title%3DSuper%2BJunior%2B%25EC%258A%2588%25ED%258D%25BC%25EC%25A3%25BC%25EB%258B%2588%25EC%2596%25B4_A-CHA_Music%2BVideo%2Cview_count%3D1815682%26author%3DYourfavoritemartian%26length_seconds%3D%2528209%252C%2529%26id%3DTUmJDVRDRTQ%26title%3DWHIP%2BYO%2BKIDS%2Bfeaturing%2BNice%2BPeter%2Cview_count%3D953666%26author%3Drecklessswaggg%26length_seconds%3D%2528241%252C%2529%26id%3DPQocCi6j_mk%26title%3DHOW%2BTO%2BLOVE%2B%2528REMIX%2529%2B-%2BJUSTIN%2BBIEBER
&endscreen_module=http%3A%2F%2Fs.ytimg.com%2Fyt%2Fswfbin%2Fendscreen-vflNhEga_.swf
&fmt_list=43%2F320x240%2F99%2F0%2F0%2C34%2F320x240%2F9%2F0%2F115%2C18%2F320x240%2F9%2F0%2F115%2C5%2F320x240%2F7%2F0%2F0
&referrer=None
&user_gender=m
&logwatch=1
&length_seconds=25
&sendtmp=1
&enablejsapi=1
&sk=764YjHpjrC6O1ctvYaH35ppV7Bd9b6mnR
&theme=dark
&t=vjVQa1PpcFM-sb-PCui5mX1jKwIXdE1yWObSxWPQFp8%3D
&video_id=M1wbceaOwfg
&p_w=P-KpDhgwPVs
&tk=SVN8E4f4bLdCNRlCrLgJIJlnzby7tCDb5dJjT08JFAX6-DLCnnC5rQ%3D%3D
&user_age=20

The information sent to the Shockwave flash video is pretty interesting. My gender and age… For us, the interesting parameter is “url_encoded_fmt_stream_map“. This parameter is URL-encoded, here it it decoded.

url=http%3A%2F%2Fo-o.preferred.fra02s03.v11.lscache4.c.youtube.com%2Fvideoplayback%3Fsparams%3Did%252Cexpire%252Cip%252Cipbits%252Citag%252Cratebypass%252Ccp%26fexp%3D903104%252C907702%26itag%3D43%26ip%3D87.0.0.0%26signature%3D30417352A65E14163FB6746AE6C6A871517A5FC9.0C91E36B690A5C885AAE0B7F43FE564444C00AD0%26sver%3D3%26ratebypass%3Dyes%26expire%3D1317600000%26key%3Dyt1%26ipbits%3D8%26cp%3DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%26id%3D335c1b71e68ec1f8&quality=medium&fallback_host=tc.v11.cache4.c.youtube.com&type=video%2Fwebm%3B+codecs%3D%22vp8.0%2C+vorbis%22&itag=43
,url=http%3A%2F%2Fo-o.preferred.fra02s03.v21.lscache2.c.youtube.com%2Fvideoplayback%3Fsparams%3Did%252Cexpire%252Cip%252Cipbits%252Citag%252Calgorithm%252Cburst%252Cfactor%252Ccp%26fexp%3D903104%252C907702%26algorithm%3Dthrottle-factor%26itag%3D34%26ip%3D87.0.0.0%26burst%3D40%26sver%3D3%26signature%3DBC4BD5E7A48929985F533325AE046E5812B24D45.E599953DFB49361BD0CCDAE3A1FD06C4C7ED5A%26expire%3D1317600000%26key%3Dyt1%26ipbits%3D8%26factor%3D1.25%26cp%3DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%26id%3D335c1b71e68ec1f8&quality=medium&fallback_host=tc.v21.cache2.c.youtube.com&type=video%2Fx-flv&itag=34
,url=http%3A%2F%2Fo-o.preferred.fra02s03.v22.lscache3.c.youtube.com%2Fvideoplayback%3Fsparams%3Did%252Cexpire%252Cip%252Cipbits%252Citag%252Cratebypass%252Ccp%26fexp%3D903104%252C907702%26itag%3D18%26ip%3D87.0.0.0%26signature%3D81FDB64A4A19D55942C6C05CE4752A209C75C00D.D45F795019B8E8214EA20037660EF2B534C817F7%26sver%3D3%26ratebypass%3Dyes%26expire%3D1317600000%26key%3Dyt1%26ipbits%3D8%26cp%3DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%26id%3D335c1b71e68ec1f8&quality=medium&fallback_host=tc.v22.cache3.c.youtube.com&type=video%2Fmp4%3B+codecs%3D%22avc1.42001E%2C+mp4a.40.2%22&itag=18
,url=http%3A%2F%2Fo-o.preferred.fra02s03.v22.lscache3.c.youtube.com%2Fvideoplayback%3Fsparams%3Did%252Cexpire%252Cip%252Cipbits%252Citag%252Calgorithm%252Cburst%252Cfactor%252Ccp%26fexp%3D903104%252C907702%26algorithm%3Dthrottle-factor%26itag%3D5%26ip%3D87.0.0.0%26burst%3D40%26sver%3D3%26signature%3DAB1BAAB6AEB36AA5449436B3B70DAEAC6CF4A309.BFF1F8A5C9179CF25B9121968EA70A0A31DE0088%26expire%3D1317600000%26key%3Dyt1%26ipbits%3D8%26factor%3D1.25%26cp%3DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%26id%3D335c1b71e68ec1f8&quality=small&fallback_host=tc.v22.cache3.c.youtube.com&type=video%2Fx-flv&itag=5

Conspicious is that the parameter is not completely decoded, but the rest is very readable. All related parameter collections are separated by a comma, their parameters with values are separated by an “&”-character but the values are URL-encoded again – here is the completely decoded version:

url=http://o-o.preferred.fra02s03.v11.lscache4.c.youtube.com/videoplayback?sparams=id%2Cexpire%2Cip%2Cipbits%2Citag%2Cratebypass%2Ccp
&fexp=903104%2C907702
&itag=43
&ip=87.0.0.0
&signature=30417352A65E14163FB6746AE6C6A871517A5FC9.0C91E36B690A5C885AAE0B7F43FE564444C00AD0
&sver=3
&ratebypass=yes
&expire=1317600000
&key=yt1
&ipbits=8
&cp=U0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4
&id=335c1b71e68ec1f8
&quality=medium
&fallback_host=tc.v11.cache4.c.youtube.com
&type=video/webm;+codecs="vp8.0,+vorbis"
&itag=43

,url=http://o-o.preferred.fra02s03.v21.lscache2.c.youtube.com/videoplayback?sparams=id%2Cexpire%2Cip%2Cipbits%2Citag%2Calgorithm%2Cburst%2Cfactor%2Ccp
&fexp=903104%2C907702
&algorithm=throttle-factor
&itag=34
&ip=87.0.0.0
&burst=40
&sver=3
&signature=BC4BD5E7A48929985F533325AE046E5812B24D45.E599953DFB49361BD0CCDAE3A1FD06C4C7ED5A
&expire=1317600000
&key=yt1
&ipbits=8
&factor=1.25
&cp=U0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4
&id=335c1b71e68ec1f8
&quality=medium
&fallback_host=tc.v21.cache2.c.youtube.com
&type=video/x-flv
&itag=34

,url=http://o-o.preferred.fra02s03.v22.lscache3.c.youtube.com/videoplayback?sparams=id%2Cexpire%2Cip%2Cipbits%2Citag%2Cratebypass%2Ccp
&fexp=903104%2C907702
&itag=18
&ip=87.0.0.0
&signature=81FDB64A4A19D55942C6C05CE4752A209C75C00D.D45F795019B8E8214EA20037660EF2B534C817F7
&sver=3
&ratebypass=yes
&expire=1317600000
&key=yt1
&ipbits=8
&cp=U0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4
&id=335c1b71e68ec1f8
&quality=medium
&fallback_host=tc.v22.cache3.c.youtube.com
&type=video/mp4;+codecs="avc1.42001E,+mp4a.40.2"
&itag=18

,url=http://o-o.preferred.fra02s03.v22.lscache3.c.youtube.com/videoplayback?sparams=id%2Cexpire%2Cip%2Cipbits%2Citag%2Calgorithm%2Cburst%2Cfactor%2Ccp
&fexp=903104%2C907702
&algorithm=throttle-factor
&itag=5
&ip=87.0.0.0
&burst=40
&sver=3
&signature=AB1BAAB6AEB36AA5449436B3B70DAEAC6CF4A309.BFF1F8A5C9179CF25B9121968EA70A0A31DE0088
&expire=1317600000
&key=yt1
&ipbits=8
&factor=1.25
&cp=U0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4
&id=335c1b71e68ec1f8
&quality=small
&fallback_host=tc.v22.cache3.c.youtube.com
&type=video/x-flv
&itag=5

Now we have got our data. There are four possible downloads (withdrawable from the type-parameter):

  1. The first download is a WebM video (a video format developed by Google) with a medium quality.
  2. The second download is a flash video with medium quality.
  3. The third download is a mp4-video with medium quality.
  4. The fourth download is a flash video with small quality.

Please note that every whole paragraph displayed in the box above is one single video url, i. e. the download url for the first video type is:

http://o-o.preferred.fra02s03.v11.lscache4.c.youtube.com/videoplayback?sparams=id%2Cexpire%2Cip%2Cipbits%2Citag%2Cratebypass%2Ccp&fexp=903104%2C907702&itag=43&ip=87.0.0.0&signature=30417352A65E14163FB6746AE6C6A871517A5FC9.0C91E36B690A5C885AAE0B7F43FE564444C00AD0&sver=3&ratebypass=yes&expire=1317600000&key=yt1&ipbits=8&cp=U0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4&id=335c1b71e68ec1f8&quality=medium&fallback_host=tc.v11.cache4.c.youtube.com&type=video/webm;+codecs="vp8.0,+vorbis"&itag=43

Now, to download this video, just download the file from this URL and you are done.

Note: It is not possible to demonstrate this function online because we need to send a request to YouTube first to retreive this URL. This is not possible because cross-domain-scripting (XSS) is not allowed by most common browsers.

In my YouTube Gadget I use the following code to download videos:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Video Downloader</title>
</head>
<body>
<h1>AJAX YouTube Video Downloader</h1>
<h2>Demo by <a href="http://robofan.de">robofan.de</a></h2>
<form onsubmit="javascript:DownloadFormats(document.getElementById('VideoURL').value); return false;">
<table cellspacing="3" border="0" cellpadding="0">
<tr><td>Video URL:</td><td><input type="text" id="VideoURL" style="width: 245px;" /></td></tr>
<tr><td>Video format:</td><td><select id="downloadformat" disabled="disabled" style="width: 250px;"><option>Enter the URL of a video first</option></select></td></tr>
<tr><td></td><td><input type="submit" value="Retreive video formats" id="downloadbutton" style="width: 250px;" /></td></tr>
</table>
</form>
<script type="text/javascript">
var Status=0;
function exactTags(text, start, end, number) //this function allows to retreive a string between to tags - example: 'tag("<tag>any text</tag>", "<tag>", "</tag>", 0);' returns "any text"
{
    var first=text.split(start);
    if(first.length > number+1)
    {
        var second=first[number+1];
        first=second.split(end);
        second=first[0];
        return second;
    }
    else
    {
        return "";
    }
}
function DownloadFormats(VideoURL)
{
    if(Status==0)
    {
        var FormatRequest = new ActiveXObject("Microsoft.XMLHTTP");
        FormatRequest.open("GET", VideoURL, true); //initialize request to retreive video URLs
        FormatRequest.onreadystatechange = function()
        {
            if(FormatRequest.readyState === 4)
            {
                if(FormatRequest.status === 200)
                {
                    document.getElementById("downloadformat").disabled=false;
                    document.getElementById("downloadformat").options.length=0;
                    document.getElementById("downloadbutton").value="Download/Show";
                    var DownloadData=decodeURIComponent(exactTags(exactTags(FormatRequest.responseText, '<param name="flashvars" value="', '"', 0), "url_encoded_fmt_stream_map=", "&", 0)).split(",");
                    for(i=0; i < DownloadData.length; i++)
                    {
                        if(decodeURIComponent(exactTags(DownloadData[i], "type=", "&", 0)).split(";")[0]!="video/webm") //If a video is not a Google WebM video
                        {
                            document.getElementById("downloadformat").options[document.getElementById("downloadformat").options.length]=new Option(decodeURIComponent(exactTags(DownloadData[i], "type=", "&", 0)).split(";")[0]+" ("+decodeURIComponent(exactTags(DownloadData[i], "quality=", "&", 0))+")", decodeURIComponent(exactTags(DownloadData[i], "url=", "&", 0))); //Annex the URL to a select-list
                           �
                        }
                    }
                    Status=1;
                }
            }
        }
        FormatRequest.send(null); //Send the request
    }
    else
    {
        window.open(document.getElementById("downloadformat").value);
        Status=0;
        document.getElementById("downloadbutton").value="Retreive video formats";
        document.getElementById("downloadformat").options.length=0;
        document.getElementById("downloadformat").options[0]=new Option("Select a video first");
        document.getElementById("downloadformat").disabled=true;
    }
}
</script>
This is a downloader for YouTube videos. Originally it was programmed for <a href="http://youtube.com">youtube-gadget.com</a>.
<p>Please note that you may - depending on your location - violate laws by downloading videos which are protected by copyright.<br/>The author does not take over responsibility for any kind of abuse of this function or these terms.</p>
</body>
</html>

This works fine for downloading any video except those which are not available in Germany. To use this function in your Internet Explorer (it will not work with other browsers) you can download the document here. (Right click -> Save as…) Please be aware that the document has to be stored in your local file system because otherwise cross domain requests to YouTube are not allowed and it will not work. For the same reason you should allow blocked running scripts or ActiveX controls.

After downloading a video you can several conversion tools to convert the videos to any format.

Thank you for reading this long article, I hope I could inspire you. Please comment.

Best Regards
Birk

Please note that you may – depending on your location – violate laws by downloading videos which are protected by copyright.
The author does not take over responsibility for any kind of abuse of this function or these terms.

My gadgets on gallery.live.com

My gadgets

Yesterday I was very shocked when I saw that Microsoft retired “gallery.live.com“. It has always been a suitable platform for submitting my gadgets which got more than 380,000 downloads (the rest of the counted 54,000 downloads came from a similar German Microsoft platform – apps.msn.de – which is luckily not offline – but new contents cannot be submitted either). Another point is that my “Gallery Gadget”, which searched for gadgets on the site, does not work anymore, users are now redirected to this page.
The page that is shown instead of the gadget platform shows following message:

The Windows Live Gallery has been retired. In order to focus support on the much richer set of opportunities available for the newest version of Windows, Microsoft is no longer supporting development or uploading of new Gadgets. However, some of the most popular and highest-rated gadgets are still available on the Gadgets page of the Windows Personalization Gallery.

With Windows Developer Preview, developers can create rich app experiences where customers focus on their important tasks. Apps are at the center of the Windows Developer Preview experience and are alive with activity and vibrant content. Users immerse themselves in your full-screen app while Windows gracefully gets out of the way.

Windows Developer Preview allows you to leverage your existing skills and code assets so you can create great experiences for your customers. Gadget and web developers can now use their HTML5 and CSS3 skills to build native Windows apps. .NET Developers can use XAML, C#, and Visual Basic to build beautiful Metro-style apps. Game developers can use the power of DirectX 11.1 to build amazing, immersive gaming experiences. Driver developers benefit from increased productivity with the new, integrated Visual Studio development environment.

(Source: gallery.live.com – October 1, 2011)

Note the third paragraph! Windows Vista and Windows 7 are both still available at the markets and they do not support gadgets anymore while XP is still supported?! Therefore I can now build metro apps for an operating system which has not even reached beta status.
Unfortunately I am not a big fan of the new metro style, I think metro style is more regress than progress. I do not want to use a computer which is not distinguishable from a mobile phone.

UPDATE (January 5, 2012):

If you are searching the gadgets which were available in the gadget gallery, you will find them all at gallery-live.com. Note the difference of the domain name, the new site contains a minus (“-”) which replaces the dot (“.”) in gallery.live.com. This service is operated by myself and not by Microsoft.

Some days ago I got a mail from a user who told me that my new YouTube Gadget could not be installed. This user got the following error: “This is not a valid gadget package.” First I thought it was en error because some files were not ready for archiving because the attribute for archiving was missing. I tried to zip the gadget completely but it did not work, neither with WinZip nor with WinRar. I read some topics on the internet but I did not found any solution. So I removed files from the archive step by step until it worked. The last file I removed was an empty file which was preserved for storing settings. So the problem was this empty file. Gadget Packages may not contain empty files or folders. I came to the result that I could create empty folders and files automatically with the file system object (FSO). Here you get some information on the MSDN: http://msdn.microsoft.com/en-us/library/z9ty6h50%28v=vs.85%29.aspx. I hope I could help you.


Today I wanted to use the htmlentities-function in JavaScript. This useful function is available for PHP but it’s not for JavaScript. The reason why I needed the htmlentities-function was the use of the element property innerHTML. I wanted to insert contents into a div container and output some JavaScript variables. The problem: As soon as any user inserts a special character, like ‘, “, >, < or & and so on, the operation fails of course. First I thought of encoding the variables by the server with an ajax request but I did not want to use up so much traffic. So I came up with this tiny function that works similar to htmlentities but encodes every character, also normal ASCII characters. It does not really encode the characters to html entites but to xml entities which is fine for its use in HTML.
Here is the function:

<script type="text/javascript">
function htmlentities(input)
{
    var code="";
    for(i=0; i < input.length; i++)
    {
        code=code+"&#"+input.charCodeAt(i)+";";
    }
    return code;
}
</script>

If you want to test it, you can do it here:

Input


Raw Output

Output with encoded entities (you will not see any change compared to the input)



This is the code for the code playground above. As you can see it is very simple.

Input
<textarea id="input" rows="3" cols="60">&#115;&#112;&#101;&#99;&#105;&#97;&#108;&#32;&#99;&#104;&#97;&#114;&#97;&#99;&#116;&#101;&#114;&#115;&#58;&#32;&#60;&#62;&#8221;&#38;&#8217;&#32;&#109;&#111;&#114;&#101;&#32;&#115;&#112;&#101;&#99;&#105;&#97;&#108;&#32;&#99;&#104;&#97;&#114;&#97;&#99;&#116;&#101;&#114;&#115;&#58;&#32;&#9835;&#9834;&#32;&#9660;&#9650;&#9660;&#9650;&#32;&#110;&#111;&#114;&#109;&#97;&#108;&#32;&#99;&#104;&#97;&#114;&#97;&#99;&#116;&#101;&#114;&#115;&#58;&#32;&#97;&#98;&#99;&#49;&#50;&#51;</textarea>
<input onclick="javascript:document.getElementById('output').value=htmlentities(document.getElementById('input').value); document.getElementById('enc_output').innerHTML=htmlentities(document.getElementById('input').value);" type="button" value="Run htmlentities()" />
Raw Output
<textarea id="output" rows="3" cols="60"></textarea>
Output with encoded entities (you will not see any change compared to the input)
<textarea id="enc_output" rows="3" cols="60"></textarea>

I just thought that unformatted code does not look so nice in my wordpress posts and because I am a self-maker and did not want to install any syntax highlighter I just wrote a little C# program which generates HTML code out of richText code. So I can simply paste code from Visual Studio and then I receive the HTML code to display my code from Visual Studio on any HTML page.
Here you can see the source code of this little tool as an example:

//C# Program that generates HTML-Code out of any programming code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        string Code;
        private void button1_Click(object sender, EventArgs e)
        {
            Code = "";
            Code += "<div class=\"coloredCode\"";
            Code += " style=\"font-family: "+richTextBox1.SelectionFont.FontFamily.Name+";\"";
            Code += "><pre style=\"white-space: pre-wrap;\">";
            System.Drawing.Color oldColor = System.Drawing.Color.Black;
            bool opened = false;
            for (int i = 0; i < richTextBox1.TextLength; i++)
            {
                richTextBox1.Select(i, 1);
                if (richTextBox1.SelectionColor != oldColor)
                {
                    if (i != 0 && opened)
                    {
                        Code += "</span>";
                        opened = false;
                    }
                    if (i != richTextBox1.TextLength - 1 && richTextBox1.SelectionColor!=System.Drawing.Color.Black)
                    {
                        Code += "<span style=\"color: " + System.Drawing.ColorTranslator.ToHtml(richTextBox1.SelectionColor) + ";\">";
                        opened = true;
                    }
                }
                Code += System.Web.HttpUtility.HtmlEncode(richTextBox1.SelectedText);
                oldColor = richTextBox1.SelectionColor;
            }
            if (opened)
            {
                Code += "</span>";
            }
            Code += "</pre></div>";
            System.Windows.Forms.TextBox textbox=new System.Windows.Forms.TextBox();
            textbox.Text = Code;
            textbox.SelectAll();
            textbox.Copy();
            MessageBox.Show("Your HTML-Code was copied to the clipboard", "Copied", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    }
}

The program can be downloaded here

Here is a progress bar for JavaScript in Windows Style. I was annoyed of the fact that there is no element for a progress bar like there is in C# or C++, I found some progress bars that looked good but they were just gif animations where the percentage could not be set using javascript. So I copied some graphics of the Windows progress bar using C# and used them in HTML/JavaScript for my bar.
Here is an example of the bar:

This is my code:

<script type="text/javascript" language="javascript" src="/Bilder/progressBar/progressBar.js"></script> <script type="text/javascript">
function updateBar()
{
	if(progress < 300)
	{
		progress++;
		setBar('Bar', progress);
		setBarText('Bar', 'Processing: '+Math.round(getPercentageFromWidth(300, progress))+'%');
	}

}
newBar("Bar", 300, "");
setBarText("Bar", "Initializing...");
var progress=0;
setTimeout('setInterval(updateBar, 10);', 5000);
</script>

while this is the content of the progressBar.js file which is included:

/* JavaScript Progress Bar - Windows Style Code written by Birk Blechschmidt, 2011 http://robofan.de This notice has to stay and may not be modified. */
function setBar(bar, pixels)
{
	document.getElementById(bar).style.width=pixels+"px";
}
function setBarText(bar, text)
{
	document.getElementById(bar+"_text").innerHTML=text;
}
function getWidthFromPercentage(barWidth, percentage)
{
	return Math.round(130*percentage/100);
}
function getPercentageFromWidth(barWidth, width)
{
	return width/barWidth*100;
}
function newBar(id, width, imagePath)
{
	if(imagePath.length > 0)
	{
		if(imagePath.substr(imagePath.length-1, 1)!="/")
		{
			imagePath=imagePath+"/";
		}
	}
	var Code='<div class="progressBarContainer" style="border: none; border-spacing: 0; width: '+width+'px; height: 23px; margin: 0; padding: 0; position: relative; top: 0; left: 0;"><div style="border: none; border-spacing: 0; margin: 0; padding: 0;"><img src="'+imagePath+'left.png" style="border: none; border-spacing: 0; margin: 0; padding: 0;" /><img src="'+imagePath+'middle.png" style="border: none; border-spacing: 0; width: '+eval(width-4)+'px; height: 23px; margin: 0; padding: 0;" /><img src="'+imagePath+'right.png" style="border: none; border-spacing: 0; margin: 0; padding: 0;" /></div><div class="greenBar" style="border: none; border-spacing: 0; position: absolute; top: 0px; left: 0px; overflow: hidden; height: 23px; white-space: nowrap; margin: 0; padding: 0; width: 0px;" id="'+id+'"><img src="'+imagePath+'left_green.png" style="border: none; border-spacing: 0; margin: 0; padding: 0;" /><img src="'+imagePath+'middle_green.png" style="border: none; border-spacing: 0; width: '+eval(width-4)+'px; height: 23px; margin: 0; padding: 0;" /><img src="'+imagePath+'right_green.png" style="border: none; border-spacing: 0; margin: 0; padding: 0;" /></div><div id="'+id+'_text" style="position: absolute; top: 1px; left: 0; overflow: hidden; width: '+width+'px; height: 23px; white-space: nowrap; text-align: center; color: black; z-index: 1; font-size: 13px;"></div></div>';
	document.write(Code);
}

I do not think this code needs an explanation.

Here you can download the zip-archive containing the images of the progress bar.

Some days ago I wanted to create a program which creates a file in a protected folder. Neither the current user nor the administrator had any access to that folder being owned by “TrustedInstaller”. I searched hours in Google trying to find out how to impersonate a user. I did not find anything useful until I found out it is not possible to impersonate “TrustedInstaller” because it is a Windows service. Also in big programming forums nobody could help me. So I was very thankful when I found this page in the web: http://blog.mikeobrien.net/2009/11/taking-ownership-and-setting-admin.html
This is the page of Mike O’Brien who blogs about his computer projects. There I found an article about how to get admin access of any system object. This system object may be a registry key, a file or a printer. At first I was very happy but then I noticed that it is not usable in .Net Framework 2.0. After some minutes I found out that it is not difficult to translate it for usage in .Net 2.0 and have done that here:

using System;
using System.Runtime.InteropServices;
using System.Security;

namespace FilePermissions
{
    class Program
    {
        public static void GrantAdministratorsAccess(string name, SE_OBJECT_TYPE type)
        {
            SID_IDENTIFIER_AUTHORITY sidNTAuthority = SECURITY_NT_AUTHORITY;

            // Create a SID for the BUILTIN\Administrators group.
            IntPtr sidAdmin = IntPtr.Zero;
            AllocateAndInitializeSid(ref sidNTAuthority, 2,
                                     SECURITY_BUILTIN_DOMAIN_RID,
                                     DOMAIN_ALIAS_RID_ADMINS,
                                     0, 0, 0, 0, 0, 0,
                                     ref sidAdmin);

            // Set full control for Administrators.
            EXPLICIT_ACCESS[] explicitAccesss = new EXPLICIT_ACCESS[1];
            explicitAccesss[0].grfAccessPermissions = ACCESS_MASK.GENERIC_ALL;
            explicitAccesss[0].grfAccessMode = ACCESS_MODE.SET_ACCESS;
            explicitAccesss[0].grfInheritance = NO_INHERITANCE;
            explicitAccesss[0].Trustee.TrusteeForm = TRUSTEE_FORM.TRUSTEE_IS_SID;
            explicitAccesss[0].Trustee.TrusteeType = TRUSTEE_TYPE.TRUSTEE_IS_GROUP;
            explicitAccesss[0].Trustee.ptstrName = sidAdmin;

            IntPtr acl = IntPtr.Zero;
            SetEntriesInAcl(1,
                            ref explicitAccesss[0],
                            0,
                            ref acl);

            // Enable the SE_TAKE_OWNERSHIP_NAME privilege.
            IntPtr token = IntPtr.Zero;
            TOKEN_PRIVILEGES tokenPrivileges = new TOKEN_PRIVILEGES();
            OpenProcessToken(GetCurrentProcess(),
                TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out token);

                LUID luid;
                LookupPrivilegeValueA(null, SE_TAKE_OWNERSHIP_NAME, out luid);
                tokenPrivileges.PrivilegeCount = 1;
                tokenPrivileges.Privileges = new LUID_AND_ATTRIBUTES[1];
                tokenPrivileges.Privileges[0].Luid = luid;
                tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

            AdjustTokenPrivileges(token, false, ref tokenPrivileges, 0,
                IntPtr.Zero, IntPtr.Zero);
            CloseHandle(token);

            // Set the owner in the object's security descriptor.
            SetNamedSecurityInfo(
                name,
                type,
                SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION,
                sidAdmin,
                IntPtr.Zero,
                IntPtr.Zero,
                IntPtr.Zero);

            // Disable the SE_TAKE_OWNERSHIP_NAME privilege.
            token = IntPtr.Zero;
            tokenPrivileges = new TOKEN_PRIVILEGES();
            OpenProcessToken(GetCurrentProcess(),
                TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out token);
            AdjustTokenPrivileges(token, false, ref tokenPrivileges, 0,
                IntPtr.Zero, IntPtr.Zero);
            CloseHandle(token);

            // Modify the object's DACL,
            SetNamedSecurityInfo(
                name,
                type,
                SECURITY_INFORMATION.DACL_SECURITY_INFORMATION,
                IntPtr.Zero, IntPtr.Zero,
                acl,
                IntPtr.Zero);

            FreeSid(sidAdmin);
            LocalFree(acl);
        }
        [StructLayoutAttribute(LayoutKind.Sequential)]
        private struct SID_IDENTIFIER_AUTHORITY
        {
            [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 6, ArraySubType = UnmanagedType.I1)]
            public byte[] Value;
        }

        [StructLayoutAttribute(LayoutKind.Sequential)]
        private struct TRUSTEE
        {
            public System.IntPtr pMultipleTrustee;
            public MULTIPLE_TRUSTEE_OPERATION MultipleTrusteeOperation;
            public TRUSTEE_FORM TrusteeForm;
            public TRUSTEE_TYPE TrusteeType;
            public IntPtr ptstrName;
        }

        [StructLayoutAttribute(LayoutKind.Sequential)]
        private struct EXPLICIT_ACCESS
        {
            public ACCESS_MASK grfAccessPermissions;
            public ACCESS_MODE grfAccessMode;
            public uint grfInheritance;
            public TRUSTEE Trustee;
        }

        [StructLayoutAttribute(LayoutKind.Sequential)]
        private struct TOKEN_PRIVILEGES
        {
            public uint PrivilegeCount;
            [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 1, ArraySubType = UnmanagedType.Struct)]
            public LUID_AND_ATTRIBUTES[] Privileges;
        }

        [StructLayoutAttribute(LayoutKind.Sequential)]
        private struct LUID_AND_ATTRIBUTES
        {
            public LUID Luid;
            public uint Attributes;
        }

        [StructLayoutAttribute(LayoutKind.Sequential)]
        private struct LUID
        {
            public uint LowPart;
            public int HighPart;
        }

        private enum TRUSTEE_TYPE
        {
            TRUSTEE_IS_GROUP,
        }

        private enum TRUSTEE_FORM
        {
            TRUSTEE_IS_SID,
        }

        private enum MULTIPLE_TRUSTEE_OPERATION { }

        public enum SE_OBJECT_TYPE
        {
            SE_UNKNOWN_OBJECT_TYPE = 0,
            SE_FILE_OBJECT,
            SE_SERVICE,
            SE_PRINTER,
            SE_REGISTRY_KEY,
            SE_LMSHARE,
            SE_KERNEL_OBJECT,
            SE_WINDOW_OBJECT,
            SE_DS_OBJECT,
            SE_DS_OBJECT_ALL,
            SE_PROVIDER_DEFINED_OBJECT,
            SE_WMIGUID_OBJECT,
            SE_REGISTRY_WOW64_32KEY
        }

        [Flags]
        private enum ACCESS_MASK : uint
        {
            GENERIC_ALL = 0x10000000,
        }

        [Flags]
        private enum SECURITY_INFORMATION : uint
        {
            OWNER_SECURITY_INFORMATION = 0x00000001,
            DACL_SECURITY_INFORMATION = 0x00000004,
        }

        private enum ACCESS_MODE
        {
            SET_ACCESS
        }

        private const string SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege";
        private static SID_IDENTIFIER_AUTHORITY SECURITY_NT_AUTHORITY =
            new SID_IDENTIFIER_AUTHORITY() { Value = new byte[] { 0, 0, 0, 0, 0, 5 } };

        private const UInt32 TOKEN_ADJUST_PRIVILEGES = 0x0020;
        private const int NO_INHERITANCE = 0x0;
        private const int SECURITY_BUILTIN_DOMAIN_RID = 0x00000020;
        private const int DOMAIN_ALIAS_RID_ADMINS = 0x00000220;
        private const int TOKEN_QUERY = 8;
        private const int SE_PRIVILEGE_ENABLED = 2;

        [DllImportAttribute("advapi32.dll", EntryPoint = "OpenProcessToken")]
        [return: MarshalAsAttribute(UnmanagedType.Bool)]
        private static extern bool OpenProcessToken(
            [InAttribute] 
    IntPtr ProcessHandle,
            uint DesiredAccess,
            out IntPtr TokenHandle);

        [DllImportAttribute("advapi32.dll", EntryPoint = "AllocateAndInitializeSid")]
        [return: MarshalAsAttribute(UnmanagedType.Bool)]
        private static extern bool AllocateAndInitializeSid(
            [InAttribute] ref SID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
            byte nSubAuthorityCount,
            uint nSubAuthority0,
            uint nSubAuthority1,
            uint nSubAuthority2,
            uint nSubAuthority3,
            uint nSubAuthority4,
            uint nSubAuthority5,
            uint nSubAuthority6,
            uint nSubAuthority7,
            ref IntPtr pSid);

        [DllImportAttribute("kernel32.dll", EntryPoint = "CloseHandle")]
        [return: MarshalAsAttribute(UnmanagedType.Bool)]
        private static extern bool CloseHandle([InAttribute] IntPtr hObject);

        [DllImportAttribute("kernel32.dll", EntryPoint = "GetCurrentProcess")]
        private static extern IntPtr GetCurrentProcess();

        [DllImportAttribute("advapi32.dll", EntryPoint = "FreeSid")]
        private static extern IntPtr FreeSid([InAttribute] IntPtr pSid);

        [DllImportAttribute("kernel32.dll", EntryPoint = "LocalFree")]
        private static extern IntPtr LocalFree(IntPtr hMem);

        [DllImportAttribute("advapi32.dll", EntryPoint = "LookupPrivilegeValueA")]
        [return: MarshalAsAttribute(UnmanagedType.Bool)]
        private static extern bool LookupPrivilegeValueA(
            [InAttribute] 
    [MarshalAsAttribute(UnmanagedType.LPStr)] 
    string lpSystemName,
    [InAttribute] 
    [MarshalAsAttribute(UnmanagedType.LPStr)] 
    string lpName,
    [OutAttribute] 
    out LUID lpLuid);

        [DllImportAttribute("advapi32.dll", EntryPoint = "AdjustTokenPrivileges")]
        [return: MarshalAsAttribute(UnmanagedType.Bool)]
        private static extern bool AdjustTokenPrivileges(
            [InAttribute()] 
    IntPtr TokenHandle,
            [MarshalAsAttribute(UnmanagedType.Bool)] 
    bool DisableAllPrivileges,
            [InAttribute()] 
    ref TOKEN_PRIVILEGES NewState,
            uint BufferLength,
            IntPtr PreviousState,
            IntPtr ReturnLength);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
        private static extern int SetNamedSecurityInfo(
            string pObjectName,
            SE_OBJECT_TYPE ObjectType,
            SECURITY_INFORMATION SecurityInfo,
            IntPtr psidOwner,
            IntPtr psidGroup,
            IntPtr pDacl,
            IntPtr pSacl);

        [DllImport("Advapi32.dll", EntryPoint = "SetEntriesInAclA",
         CallingConvention = CallingConvention.Winapi,
         SetLastError = true, CharSet = CharSet.Ansi)]
        private static extern uint SetEntriesInAcl(
            int CountofExplicitEntries,
            ref EXPLICIT_ACCESS ea,
            uint OldAcl,
            ref IntPtr NewAcl);
        static void Main(string[] args)
        {
            GrantAdministratorsAccess("Machine\\Key", SE_OBJECT_TYPE.SE_REGISTRY_KEY);
        }
    }
}

Code by Mike O’Brien, Source: http://blog.mikeobrien.net/2009/11/taking-ownership-and-setting-admin.html; Code is modified for usage in .Net 2.0

This code grants admin access to the folder “Test” located on the hard drive “C:”. Now it is possible for the program to edit the directory.
To get access for any registry key the method would look like this:

GrantAdministratorsAccess(“Machine\\Key”, SE_OBJECT_TYPE.SE_REGISTRY_KEY);

Note that the local machine just has to be called “MACHINE”.

Since I changed my blog system to WordPress, I recognize more visitors. One more thing to say is that already in the first three days two visitors commented my posts although my server had massive problems, while I had only three comments on my old blog – in its total running time. I guess wordpress is friendlier to search engines. I also decided to blog more frequently. The design of my blog looks much better than the old one and it loads much more quickly because of the new server. The WordPress weblog can now be designed more individually and for the administrator there are much more options available.

Greetings from vacations (Turracher Höhe, Austria)

Today I installed the English Version of Microsoft Visual C# 2010 Express Edition to make English screenshots for a tutorial. My problem was that I could not release my program. Only a green triangle was shown which allowed me to debug my program, not to release it. Here is a step-by-step tutorial how to enable the release debug in Microsoft Visual C# 2010 Express.