tag:blogger.com,1999:blog-67470672024-03-13T07:09:07.037-07:00Darin Creason's WeblogA splat of all my blathering.Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.comBlogger30125tag:blogger.com,1999:blog-6747067.post-1167945353992840112007-01-04T12:55:00.000-08:002007-01-04T13:21:53.800-08:00What Superhero Am I?<TABLE><TR><TD>Green Lantern</TD><br /><TD><HR ALIGN=LEFT NOSHADE SIZE=4 WIDTH=75></TD><TD> 75%</TD><br /></TR><TR><TD>The Flash</TD><br /><TD><HR ALIGN=LEFT NOSHADE SIZE=4 WIDTH=70></TD><TD> 70%</TD><br /></TR></TABLE><br /><IMG SRC="http://www.thesuperheroquiz.com/pics/lantern2.jpg"><br />(Hot-headed. You have strong will power and a good imagination.)<br /><br /><A HREF="http://www.thesuperheroquiz.com/"><br />Click here to take the Superhero Personality Test</A>Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0tag:blogger.com,1999:blog-6747067.post-1092118198468829132004-08-09T23:06:00.000-07:002004-08-09T23:09:58.470-07:00What OS am I?It shouldn't suprise you all that much. :)
<br />
<br /><a href="http://bbspot.com/News/2003/01/os_quiz.php"><img src="http://www.bbspot.com/Images/News_Features/2003/01/os_quiz/xp.jpg" width="300" height="90" border="0" alt="You are Windows XP. Under your bright and cheerful exterior is a strong and stable personality. You have a tendency to do more than what is asked or even desired."><br>Which OS are You?</a>Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0tag:blogger.com,1999:blog-6747067.post-1089960164381838072004-07-15T23:37:00.000-07:002004-07-15T23:42:44.380-07:00A new XP gemI ran across this little gem today and thought I'd share it with everyone.
<br />
<br />
<br /><span style="font-size:85%;">As long as your computer is not a domain member, you don't have to limit the number of user accounts, and you don't need TweakUI to get Windows to skip the welcome screen or prompt the user to logon.</span>
<br />
<br /><span style="font-size:85%;">At a command prompt, enter <strong>control userpasswords2</strong>. This will launch the User Accounts application. On the Users tab, clear the check box for "Users must enter a user name and password to use this computer" and click OK. (If your computer is part of a domain, this box does not appear). The Automatically Log On dialog box appears. Type your user name and password, and click OK</span>
<br /><span style="font-size:85%;"></span>
<br /><span style="font-size:85%;">If you didn't know to look for it, you'd never find this handy dialog, which is available in both XP Professional and XP Home. And it's effective—two readers who found TweakUI didn't work for them were able to bypass the welcome screen using this technique. This dialog also lets you define a particular account as a Standard user, a status in between the Limited user and Administrator user categories available in the Control Panel's normal User Accounts applet.</span>
<br />Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0tag:blogger.com,1999:blog-6747067.post-1089834841073231252004-07-14T12:53:00.000-07:002004-07-14T13:08:49.906-07:00Not all keys are created equalLet's take a quick walk in the realm of things that are possibly reasonable but certainly not obvious.
<br />
<br />Given the following code, what are the values of b1-b4?
<br /><CODE>
<br />  Hashtable h = new Hashtable();
<br />  h.Add(1, 1);
<br />  h.Add((uint)2, 1);
<br />  bool b1 = h.ContainsKey(1);
<br />  bool b2 = h.ContainsKey((uint)1);
<br />  bool b3 = h.ContainsKey(2);
<br />  bool b4 = h.ContainsKey((uint)2);
<br /></CODE>
<br />b1 is true
<br />b2 is false
<br />b3 is false
<br />b4 is true
<br />
<br />Furthermore, consider the following:
<br /><CODE>
<br />  object i = 5;
<br />  object j = (uint)5;
<br />  int h1 = i.GetHashCode();
<br />  int h2 = j.GetHashCode();
<br /></CODE>
<br />The values of h1 and h2 are both 5. What gives?Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com1tag:blogger.com,1999:blog-6747067.post-1089650452971946392004-07-11T23:15:00.000-07:002004-07-12T09:42:49.946-07:00Getting Winamp to play RealAudio streams<strong>I take no credit for this. I just found it very useful but difficult to find so I thought I would re-post it for the masses.</strong>
<br />
<br />My friend Lars loves to listen to German radio. It could be because he is German but I'm not sure. ;) His favorite station is <a href="http://www.fritz.de">Fritz.de</a> and he listens to it via a RealAudio stream while he is staying here. That meant of course that he had to install the evil RealPlayer. I hate RealPlayer because it takes over my machine and makes me paranoid so I was compelled to seek another solution. I found a posting on a news forum that describes how to use the RealPlayer codecs by installing the <a href="http://www.musiclivesonline.com/software/downloads/Tara_v1.0.3b.exe">Tara's RealAudio input plug-in</a>. Thanks Tara whoever you are. This plug-in rocks and I appreciate you taking the time to write it. Also thanks to Arman68 for re-posting his older post so I could re-post it. I'm confused.
<br />
<br />This is the post unaltered and in its entirety. Enjoy!
<br />
<br /><hr>
<br /><blockquote>Arman68
<br />
<br />Here's a workaround that I found while perusing the Winamp forums. I'm afraid I don't know who came up with it but to them all credit is due. Eventhough it was written with Win 98/ME in mind, it works like a charm with Win2K assuming you do the necessary modifications like changing all references of C:\Windows to C:\WINNT etc. Enjoy.
<br /><hr>
<br />
<br />Real Player Workaround
<br />
<br />Winamp Realaudio plugins require Realplayer to be installed, I know that, there has been a lot of discussion about this here. Well, I think Realplayer is a bloated software which puts way too much entries in the registry and I hate those types of softwares.
<br />
<br />I found a way to keep the minimal components required in order to hear Realaudio content in winamp. (tested innover's and Tara's plugins, on Winamp 2.76, Win98SE, Realplayer 7 & 8). Tara's plugin even allows playback of realvideo.
<br />
<br />Here is what you must do :
<br />
<br />1- Install Realplayer (I suggest a registry backup before, if you want to avoid the hundreds of registry entries it puts in your registry when only 3 are needed)
<br />
<br />2- Backup those 3 folders :
<br />
<br />c:\program files\common files\real\common
<br />c:\program files\common files\real\plugins
<br />and
<br />c:\program files\common files\real\codecs
<br />
<br />* almost forgot, also backup the pncrt.dll file located in c:\windows\system * (or C:\winnt\system) for Win2K
<br />
<br />3. Uninstall Realplayer and restore your registry if you did a backup as suggested in #1
<br />
<br />4. Copy the 3 folders you backed up to their original locations, and pncrt.dll file to c:\windows\system
<br />
<br />5. Paste the text below in notepad and save as a .reg file
<br />
<br />REGEDIT4
<br />
<br />[HKEY_CLASSES_ROOT\Software\RealNetworks\Preferenc
<br />es\DT_Plugins]
<br />@="C:\\Program Files\\Common files\\Real\\Plugins\\"
<br />
<br />[HKEY_CLASSES_ROOT\Software\RealNetworks\Preferenc
<br />es\DT_Codecs]
<br />@="C:\\Program Files\\Common files\\Real\\Codecs\\"
<br />
<br />[HKEY_CLASSES_ROOT\Software\RealNetworks\Preferenc
<br />es\DT_Common]
<br />@="C:\\Program Files\\Common files\\Real\\Common\\"
<br />
<br />
<br />6. Click on the .reg file you just saved.
<br />
<br />7. Enjoy, of course you must have one of the winamp realplayer plugins. (For example, Tara 1.0.3.b.exe)
<br /><hr>
<br />(the post is slightly wrong in that on NT/Win200/WinXp/Win2003 the folder is system32 and not system)</blockquote>Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com3tag:blogger.com,1999:blog-6747067.post-1087426111804011892004-06-16T15:47:00.000-07:002004-06-16T15:48:31.803-07:00What's the difference between I19 and I18N?Nothing. But here's a load of useful stuff on both:
<br />
<br /><a href="http://www.hanselman.com/blog/PermaLink.aspx?guid=c78a0757-ebd7-4e9e-b4f5-84f71c032e34">Iñtërnâtiônàlizætiøn</a>
<br />Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0tag:blogger.com,1999:blog-6747067.post-1086158827378119962004-06-01T23:47:00.000-07:002004-06-01T23:55:30.410-07:00Best sci-fi/fantasy books of all time?This is my list (in order)
<br /><a href='http://photos1.blogger.com/img/297/1051/640/eye_of_sauron.jpg'><img border='0' style='border:1px solid #000000; margin:2px' src='http://photos1.blogger.com/img/297/1051/320/eye_of_sauron.jpg' align="right"></a>
<br />1. <a href="http://www.tolkien.co.uk/books/lotr.asp">Lord of the Rings Trilogy</a> by <a href="http://www.tolkien.co.uk/jrrtolkien/biography.asp">J.R.R Tolkien</a>
<br />2. <a href="http://www.dunenovels.com/books/dune.html">Dune</a> by <a href="http://www.dunenovels.com/books/dreamer.html">Frank Herbert</a>
<br />3. <a href="http://www.stephenking.com/DarkTower/">The Dark Tower Series</a> by <a href="http://www.stephenking.com/biography.php">Stephen King</a>
<br />4. <a href="http://www.dunenovels.com/books/children.html">Children of Dune</a> by <a href="http://www.dunenovels.com/books/dreamer.html">Frank Herbert</a>
<br />
<br />
<br />
<br />If I had ever gotten around to reading Asimov I'm sure his Foundation Series would have ranked high as well.
<br />
<br />Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com3tag:blogger.com,1999:blog-6747067.post-1085681999421164362004-05-27T11:17:00.000-07:002004-05-27T11:19:59.420-07:00Optional SOAP headersThere is no way to specify if a header is optional or required within WSDL 1.1. The SOAP spec allows headers to be introduced to a SOAP message even when they are not declared in WSDL. For that reason, the WS-I Basic Profile 1.0 has chosen to interpret the presence of a header binding in the WSDL as always being required.
<br />
<br />The following two sections from the WS-I Basic Profile 1.0 describe this
<br />
<br />5.6.22 Required Headers
<br />
<br />WSDL 1.1 does not clearly specify whether all soapbind:headers specified on the wsdl:input or wsdl:output elements of a wsdl:operation element in the SOAP binding section of a WSDL description must be included in the resultant SOAP messages when they are transmitted. The Profile makes all such headers mandatory, as there is no way in WSDL 1.1 to mark a header optional.
<br />
<br />R2738 A MESSAGE MUST include all soapbind:headers specified on a wsdl:input or wsdl:output of a wsdl:operation of a wsdl:binding that describes it.
<br />
<br />5.6.23 Allowing Undescribed Headers
<br />
<br />Headers are SOAP's extensibility mechanism. Headers that are not defined in the WSDL description may need to be included in the SOAP messages for various reasons.
<br />
<br />R2739 A MESSAGE MAY contain SOAP header blocks that are not described in the wsdl:binding that describes it.
<br />
<br />R2753 A MESSAGE containing SOAP header blocks that are not described in the appropriate wsdl:binding MAY have the mustUnderstand attribute on such SOAP header blocks set to '1'.
<br />Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0tag:blogger.com,1999:blog-6747067.post-1085681807317816992004-05-27T10:52:00.000-07:002004-05-27T11:16:47.316-07:00Regular expressions and Star TrekI don't know what it is about regular expressions but I just love 'em.
<br />
<br />Do you remember that episode of Star Trek TNG where Ryker brought back a game from Risa? It looked like one of those new personal computers that people wear on their heads (only this one shot rays of light into the wearer's eyes). Anyway, as you played the game you became addicted because it somehow tapped into the pleasure centers of the player's brain. (How much would you pay for a Game Cube that could give you an orgasm?) As you progressed to higher and higher levels of the game the amount of 'whatever it was that it gave you' increased. Each time a player completed a level they would get a pleasure reward.
<br />
<br />That's exactly how I feel when I find a new regular expression. Kind of perverse huh? If you know what I mean then you might find the list of <a href="http://www.3leaf.com/resources/articles/regex.aspx">useful regex's maintained by Scott at 3 Leaf</a> pleasuring.
<br />
<br />Thanks for doing this Scott. (And sorry for bringing you in on this sorted fetish.)
<br />Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0tag:blogger.com,1999:blog-6747067.post-1085680306399822652004-05-27T10:46:00.000-07:002004-05-27T10:51:46.400-07:00Invoking WSDL and XSDWhen you invoke WSDL.exe you need to make sure that you specify the names of all of the imported schema and WSDL files on the command line. Although, you probably gave a schemaLocation within the import statement this is just a hint at the location and these tools do not attempt to load the files from this location.
<br />
<br />If you are using WSDL and XSD a lot you <strong>MUST</strong> take a look at <a href="http://www.gotdotnet.com/Community/Workspaces/workspace.aspx?id=80258a8c-bb4c-48e6-948b-05f6da568f55">Point2's code generation toolkit</a>. It rocks!Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0tag:blogger.com,1999:blog-6747067.post-1082674828249639162004-04-22T15:58:00.000-07:002004-06-01T22:04:02.393-07:00Base64 and URL EncodingsHere's a useful site for testing encodings <a href="http://ostermiller.org/calc/encode.html">http://ostermiller.org/calc/encode.html</a>Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0tag:blogger.com,1999:blog-6747067.post-1082429794663511782004-04-19T18:28:00.000-07:002004-06-01T22:04:47.043-07:00Instant Runoff Voting<a href="http://fairvote.org/irv/whatis2.htm">http://fairvote.org/irv/whatis2.htm</a>
<br />
<br />Why don't we use this form of voting? Makes me wonder...Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0tag:blogger.com,1999:blog-6747067.post-1081473065632464942004-04-19T16:39:00.000-07:002004-06-01T22:05:04.596-07:00Mounting the projector There are many different ways to mount a projector. I decided to mount mine to the ceiling so that it would be out of the way. I looked into the projector mount kits that are sold at projector retail sites. There are many, many to choose from. The first thing to check out is the plate that screws to your projector. They make some that are static (made specially to fit a project model) and some that are flexible (they have spider arms that adjust to any angle and reach) to fit almost any projector. The next thing you need to decide is how far the projector will extend from the base. In my case I needed the projector to drop down about 10" from the ceiling because the image would otherwise be blocked by the basement ducting. These <a href="http://www.mountsandmore.com/asp/show_detail_2.asp?sku=PE0116&catid2=173">extensions</a> are also available but are really quite pricey considering what they are. In fact, the pipe they use is the same that you can buy at Home Depot for plumbing. It's just 1 1/2" NPT (National Pipe Thread, the kind we use in America) metal pipe. I bought my 6" piece at Home Depot for about $3. I also found a floor flange that I could bolt to the ceiling and screw the pipe into. That just left me with the plate that attaches to the projector. The plate comes with an attachment that has a female connector to connect to the pipe hanging from the ceiling. I bought <a href="http://www.mountsandmore.com/asp/show_detail.asp?sku=PE0147">this part</a> online at <a href="http://www.mountsandmore.com/">Mounts and More</a> for $149.50. I wanted to buy this part instead of making it myself so that I was sure that it would fit my projector and because it comes with a very nice ball-in-socket design for precision adjustments. You'd be surprised how much the image moves on a wall 16' away when you move the project 1" on axis. (In fact, the answer is that it moves 32".) It also comes with an easy way to detach the projector so that I can remove it for cleaning or using it elsewhere.
<br />
<br />I bought a can of black paint and painted both the flange and the threaded pipe that I bought from Home Depot. Then I mounted the flange to the ceiling using 2 1/2" machine bolts. I pre-drilled the holes in a ceiling joist for two of the bolts and used expansion anchors on the other two since they were in drywall only. I weight about 150lbs and was able to hang from it. I then screwed the threaded piece from the project mount part to the pipe. I attached the projector mount to the projector using the supplied screws and then finally attached the projector to the ceiling mount. Using an Allen wrench supplied with the mount plate I tightened down the screws that lock the project in place and was ready to go.
<br />
<br />The next thing was to wire the video cables and electrical outlet right next to the mount so that I wouldn't have to run exposed cables. I'll talk about making your own component video cables in an upcoming blog.Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0tag:blogger.com,1999:blog-6747067.post-1081472237624731792004-04-19T15:20:00.000-07:002004-06-01T22:05:24.640-07:00Choosing a home theater projector screen: Part 3 SizeNow lastly but perhaps most importantly I needed to decide how large of a screen I wanted. This is important because people who have no idea about all this work that goes into building a home theater really only comment about one thing... the size factor. "Wow, look at the size of that screen! That's awesome."
<br />
<br />I talked with several people about this topic at my local stores and as usual, I got several differing opinions. Some said that quality was more important than size (and that is the tradeoff) and some said that bigger was the only way to go.
<br />
<br />In my case I had some limitations because my room is quite small. I also had to figure in what my projector would be capable of doing in quality. I wanted around a 100" diagonal on my viewing area so that meant that I needed a screen that was 6 x 8 (recall that I went with the 4:3 format). I checked DaLite's site for a price on the Model C in this configuration and found that it was about $265. That was indeed very pleasing to me but I wasn't ready to give in just yet. I'm frugal (if you haven't already noticed) and I wanted to check around for better pricing. As it turns out DaLite's price was very good and the only reason that I didn't buy it directly from their website was that I found a local store that would price match. This turns out to have been a great idea because the screen was delivered damaged. I think that this is very rare and the local store was very apologetic (they could see the tears streaming down my face) and helpful. I got the replacement screen 5 business days later and installed it the following weekend.
<br />
<br />Since my room is still being finished I just have bare studs on the wall where the screen is going. I had some 3" x 1/4" lag bolts laying around so I put them into the wall and used washers to secure the screen frame. I just couldn't wait to see what my projector and screen would look like together.
<br />
<br />I hadn't mounted the projector yet because I still wanted some flexibility after seeing what it looked like with the screen. I sat the projector on top of a really heavy shelf and leveled it with a blanket. It turns out that I was within about 6" of my ideal size. With the 1.2x zoom capabilities of the X1 I could easily scale the image to the 100" diagonal. I was very pleased at how everything was turning out. My next task was to mount the projector on the ceiling.Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0tag:blogger.com,1999:blog-6747067.post-1082397640097944562004-04-19T10:50:00.000-07:002004-06-01T22:05:48.163-07:00Step-up voltage transformersLast week I wanted to buy a device that would take my 110V outlet and allow me to plug in a 220V appliance. I wanted the device to be installed permanently in the wall so that I could use it frequently.
<br />
<br />What I found is that I can't do this. First of all I couldn't find such a device anywhere. I also found out that putting such a device directly in the wall doesn't meet code. Apparently, the electric company doesn't like such things attached directly to the grid. The solution that I found was to buy a <a href="http://www.220-electronics.com/Transformers/trans/simranconverter.htm">step-up voltage transformer</a>.
<br />
<br />While I was researching I found a couple interesting sites.
<br /><a href="http://www.currentsolutions.com/knowledge/country_spec_a-g.htm">http://www.currentsolutions.com/knowledge/country_spec_a-g.htm</a>
<br /><a href="http://www.german-way.com/german/electric.html">http://www.german-way.com/german/electric.html</a>Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0tag:blogger.com,1999:blog-6747067.post-1081979185848932362004-04-14T14:20:00.000-07:002004-07-14T09:22:11.783-07:00RCWs and reference countingOver the last couple of days I have been working with a couple of my team members to identify a problem with our DCOM server interacting with a managed class implementing a CCW. In the method call to the CCW the DCOM server passes a COM interface which the managed class uses via an RCW. We were seeing the DCOM server crashing at pretty regular intervals and they always coincided with a .NET garbage collection. It turns out that the problem was in the DCOM server code but during our testing I found some important things that I didn't know before about RCWs.
<br />
<br />When an interface is passed to a managed object an RCW is used. As I understand it, in this simple case (no cross-AppDomain marshalling), the RCW will hold a single reference to this interface which effectively bumps the reference count by 1. When the RCW is no longer referenced it will be garbage collected and during this process Release will be called which will decrement the count by 1. Note, that this *could* result in the COM object being deleted. While inside the method call the interface is still being referenced so will not be garbage collected right away. This is true even if you call GC.Collect();GC.WaitForPendingFinalizers();. However, the very next time the GC is run this object could be collected.
<br />
<br />Please note that this behavior is not a bug. It is a known feature of the .NET runtime and well documented. I'm just pointing out that it may not be immediately obvious.
<br />
<br />Consider this example (error checking removed for brevity):
<br />
<br /><DIV style="BORDER-RIGHT: 1px solid; BORDER-TOP: 1px solid; OVERFLOW: auto; BORDER-LEFT: 1px solid; BORDER-BOTTOM: 1px solid; HEIGHT: 177px"><CODE><PRE>
<br />// in the DCOM server code
<br />void CServer::ExecutePlugin()
<br />{
<br />  CComPtr<IPlugin> pPlugin = 0;
<br />  HRESULT hr = pPlugin.CoCreateInstance(L"MyPlugin.MyPlugin", 0, CLSCTX_SERVER);
<br />  CComPtr<ISession> pSession = 0;
<br />  hr = pSession.CoCreateInstance(L"Server.Session.1", 0, CLSCTX_SERVER);
<br />  hr = pPlugin->Execute(pSession);
<br />}
<br />
<br />// in the plug-in code
<br />[ProgId("MyPlugin.MyPlugin")]
<br />[Guid("0B5AD27C-488E-4988-A069-83E8CB6BF27B")]
<br />class Plugin : IPlugin
<br />{
<br />  public void Execute(MySession session)
<br />  {
<br />    GC.Collect();
<br />    GC.WaitForPendingFinalizers();
<br />  }
<br />}
<br /></CODE></PRE></DIV>
<br />After the call to pPlugin->Execute(pSession) has returned the reference count on the pSession object will be (at least) 2. One for the initialize CCI and one for the RCW created for the managed plug-in. After the local CComPtr is deleted the reference count will be 1. This means that the object will not be deleted within the scope (or thread) of the CServer::Execute method. In fact, with some trivial tracing added you can see that the destructor of the pSession object is called from a different thread altogether. This thread must be the GC thread that is cleaning up the RCW for the ISession object.
<br />
<br />The reason why this is important to keep in mind is that if the DCOM server was not correctly following the rules of COM interface reference counting of the ISession object, then the resulting bug would not manifest itself so easily if the plug-in were written in unmanaged code as it would in the managed case.
<br />
<br />Most, implementors of the IPlugin interface would realize that the ISession interface handed to their Execute method does not require an AddRef and Release since it is not being copied and so the reference count would remain at 1 for the entire lifetime of the CServer::Execute call and the object would be destroyed when the CComPtr left scope. In this case the object would be destroyed on the same thread as it was created and not some other .NET GC thread.
<br />
<br />In the managed case the RCW will most likely be the last reference to the pSession object and therefore release it only when GC'd. If the COM object was deleted prematurely because of not following the rules of COM, this might manifest itself as some kind of null derefence exception or crash.Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com1tag:blogger.com,1999:blog-6747067.post-1081891793303053232004-04-13T14:29:00.000-07:002004-06-01T22:06:33.603-07:00Detecting which .NET Framework version is installed?<a href="http://blogs.msdn.com/robvi/archive/2004/02/17/75272.aspx">How do I detect what .NET Framework version is installed on a machine?</a>Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0tag:blogger.com,1999:blog-6747067.post-1081887721538309502004-04-13T13:20:00.000-07:002004-07-14T09:19:25.630-07:00Using CAPICOM and OpenSSLI was recently challenged with a project that required sending a secure message from a Windows network to a *nix network. The client insisted that we use CAPICOM on the Windows side and the partner on the *nix side was adamant about using OpenSSL. I figured since both libraries were capable of support PKI they must be compatible but I was unsure of how. I was also skepticle because CAPICOM is notorious for its proprietary implementation. After many unsuccessful attempts, talking with folks at Microsoft, and reading gads of web pages on the subject I was becoming quite unsure that it could be done. However, MS suggested that it was possible and that the PKI implementation of CAPICOM did support the standards. The trick was to figure out how.
<br />
<br />After quite a bit of reading and playing with <a href="http://www.slproweb.com/products/Win32OpenSSL.html">OpenSSL for Win32</a>, I was able to come up with a way to use <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnsecure/html/intcapicom.asp">CAPICOM 2.0</a> and OpenSSL together to send a secure message. The key was with the S/MIME capabilities of OpenSSL.
<br />
<br />In my situation I needed to sign and envelope a message using CAPICOM (on Windows of course) and send the message to a *nix machine using OpenSSL to decrypt and verify it.
<br />
<br />For this example I will use VB 6.0 (sorry) to drive the CAPICOM calls. I am following the best practices of PKI solutions such as PGP as closely as I could (I think). In particular, I am embedding the plain-text content within the signature for use in the verification process later. The signature is then encrypted within the envelope so that only a single file needs to be sent. This results in a slightly larger envelope but simplifies the process by not requiring separate messages to be sent.
<br />
<br />One thing to note is that CAPICOM is a scriptable COM interface and therefore uses BSTR as the string format of choice. This means that all content will be represented in UNICODE and will require translation on the server so that *nix tools like OpenSSL can interpret them.
<br />
<br />The following VB code shows 4 sub-routines that read, write, sign, and encrypt a clear-text text file as well as an event sub-routine for a simple form with a single button for kicking the process off.
<br />
<br />I am simplifying the example by removing the error handling and making some assumptions about the storage of the certificates being used. I am assuming that the certificates are stored in the local user store called “My” and that the certificate location is known. Almost certainly, neither of these would be the case in the real world.
<br />
<br /><DIV style="BORDER-RIGHT: 1px solid; BORDER-TOP: 1px solid; OVERFLOW: auto; BORDER-LEFT: 1px solid; BORDER-BOTTOM: 1px solid; HEIGHT: 177px"><CODE><PRE>' I do not claim any responsibility for the correctness or security of this code
<br />' and any or all portions should be used at your own risk.
<br />
<br />Option Explicit
<br />Const ForReading = 1, ForWriting = 2, TristateFalse = 0
<br />Const TemporaryFolder = 2
<br />
<br />Private Sub Command1_Click()
<br />  SignFile "c:\temp\in.txt", "c:\temp\signed.txt"
<br />  EnvelopeFile "c:\temp\signed.txt", "c:\temp\smime.txt"
<br />End Sub
<br />
<br />Sub SignFile(ByVal sInFile As String, ByVal sOutFile As String)
<br />  ' Open the MY store and retrieve the first certificate from the
<br />  ' store. The signing operation will only work if this certificate is
<br />  ' valid and has access to the signer's private key.
<br />  Dim oCertStore As New Store
<br />  oCertStore.Open CAPICOM_CURRENT_USER_STORE, "My", CAPICOM_STORE_OPEN_READ_ONLY
<br />  
<br />  Dim oSigner As New signer
<br />  ' The signer's certificate is at index 1
<br />  oSigner.Certificate = oCertStore.Certificates.Item(1)
<br />  Set oCertStore = Nothing
<br />  
<br />  ' Set the content to be signed.
<br />  Dim oSignedData As New SignedData
<br />  oSignedData.Content = ReadFile(sInFile)
<br />  
<br />  ' Save the time the data was signed as a signer attribute
<br />  ' NOTE: the name 'Attribute' is not a unique name
<br />  ' and must be preceded by 'CAPICOM.'
<br />  Dim oSigningTimeAttr As New CAPICOM.Attribute
<br />  oSigningTimeAttr.Name = CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME
<br />  oSigningTimeAttr.Value = Now
<br />  oSigner.AuthenticatedAttributes.Add oSigningTimeAttr
<br />  
<br />  ' Sign the content using the signer's private key.
<br />  ' A value of 'True' in the second parameter indicates that the
<br />  ' content signed is not included in the signature string.
<br />  ' A value of 'False' indicates that it is
<br />  Dim s As String
<br />  s = oSignedData.Sign(oSigner, False, CAPICOM_ENCODE_BASE64)
<br />
<br />  ' Strip off the last blank line
<br />  s = Mid(s, 1, Len(s) - 2)
<br />  ' Add the PKCS #7 header and footer so that the signature conforms to what
<br />  ' OpenSSL expects.
<br />  s = "-----BEGIN PKCS7-----" + vbCrLf + s + vbCrLf + "-----END PKCS7-----"
<br />  WriteFile sOutFile, s
<br />  
<br />  Set oSignedData = Nothing
<br />  Set oSigner = Nothing
<br />  Set oSigningTimeAttr = Nothing
<br />End Sub
<br />
<br />Sub EnvelopeFile(ByVal sInFile As String, ByVal sOutFile As String)
<br />  ' Open the MY store and retrieve the first certificate from the
<br />  ' store. The signing operation will only work if this certificate is
<br />  ' valid and has access to the signer's private key.
<br />  Dim oCertStore As New Store
<br />  oCertStore.Open CAPICOM_CURRENT_USER_STORE, "My", CAPICOM_STORE_OPEN_READ_ONLY
<br />  
<br />  ' Declare and initialize an EnvelopedData object
<br />  Dim oEnvelopedData As New EnvelopedData
<br />  oEnvelopedData.Content = ReadFile(sInFile)
<br />  
<br />  ' The signer's certificate is at index 1
<br />  ' NOTE that you can add as many recipient certs as you like.
<br />  oEnvelopedData.Recipients.Add oCertStore.Certificates.Item(1)
<br />  Set oCertStore = Nothing
<br />  
<br />  ' Set the encryption algorithm and key length. Comment out
<br />  ' or remove the following lines to use the default algorithm
<br />  ' and key length. The triple DES algorithm and 128 bit key
<br />  ' length may not be supported.
<br />  oEnvelopedData.Algorithm.Name = CAPICOM_ENCRYPTION_ALGORITHM_3DES 'or ENCRYPTION_ALGORITHM_RC4
<br />  oEnvelopedData.Algorithm.KeyLength = CAPICOM_ENCRYPTION_KEY_LENGTH_128_BITS
<br />
<br />  'Declare the string that will hold the enveloped message.
<br />  Dim sEnvelopedMessage As String
<br />
<br />  'Encrypt the message into sEnvelopedMessage. The enveloped message
<br />  'string contains everything that an intended recipient will need to
<br />  'decrypt the message, including information on the encryption algorithm 'key length.
<br />  sEnvelopedMessage = oEnvelopedData.Encrypt
<br />
<br />  ' Release the EncryptedData object and the Store object.
<br />  Set oEnvelopedData = Nothing
<br />
<br />  ' Add the MIME headers to the content
<br />  Dim sMimeHeader As String
<br />  sMimeHeader = "MIME-Version: 1.0" + vbCrLf
<br />  sMimeHeader = sMimeHeader + "Content-Disposition: attachment; filename=""smime.p7m""" + vbCrLf
<br />  sMimeHeader = sMimeHeader + "Content-Type: application/x-pkcs7-mime; name=""smime.p7m""" + vbCrLf
<br />  ' these last two line feeds are important
<br />  sMimeHeader = sMimeHeader + "Content -Transfer - Encoding: base64" + vbCrLf + vbCrLf
<br />
<br />  sEnvelopedMessage = sMimeHeader + sEnvelopedMessage
<br />
<br />  WriteFile sOutFile, sEnvelopedMessage
<br />End Sub
<br />
<br />Sub WriteFile(ByVal sFileName As String, ByVal sText As String)
<br />  Dim oFS, oTF As Object
<br />  Set oFS = CreateObject("Scripting.FileSystemObject")
<br />  Set oTF = oFS.OpenTextFile(sFileName, ForWriting, True, TristateFalse)
<br />  oTF.Write (sText)
<br />  oTF.Close
<br />  Set oTF = Nothing
<br />  Set oFS = Nothing
<br />End Sub
<br />
<br />Function ReadFile(ByVal sFileName As String) As String
<br />  Dim oFS, oTF As Object
<br />  Set oFS = CreateObject("Scripting.FileSystemObject")
<br />  Set oTF = oFS.OpenTextFile(sFileName, ForReading, False, TristateFalse)
<br />  ReadFile = oTF.ReadAll
<br />  oTF.Close
<br />  Set oTF = Nothing
<br />  Set oFS = Nothing
<br />End Function
<br /></PRE></CODE></DIV>
<br />Then to decrypt and verify the message you can use the OpenSSL command-line tools with the smime command.
<br />
<br />This first command will take the envelope and decrypt it to find the signature (containing the plain-text content).
<br /><code>
<br />openssl smime -decrypt -in smime.txt -recip ..\cert.pem -inkey ..\privkey.pem -out signature.unicode.txt
<br /></code>
<br />Recall that the output from CAPICOM is always UNICODE so we need to translate the files back to ANSI before proceeding. I use a simple tool that I wrote to do this.
<br /><code>
<br />Unicode2AnsiConvert.exe signature.unicode.txt signature.txt
<br /></code>
<br />This second command will take the signature and verify it. If the signature is verified the tool will write “Verification successful” to the console. Please note that verification requires correct certificate resolution to be configured for the machine but this is necessary for security.
<br /><code>
<br />openssl smime -verify -in signature.txt -inform PEM -out message.unicode.txt
<br /></code>
<br />Finally, translate the message to ANSI.
<br /><code>
<br />Unicode2AnsiConvert.exe message.unicode.txt message.txt
<br /></code>
<br />The resulting message.txt file will contain the original message input into CAPICOM.Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com1tag:blogger.com,1999:blog-6747067.post-1081870612171436082004-04-13T08:35:00.000-07:002004-06-01T22:07:24.023-07:00The Man In The ArenaWhy can't we get a president that can speak like this again?
<br />
<br /><a href="http://www.theodore-roosevelt.com/trsorbonnespeech.html">http://www.theodore-roosevelt.com/trsorbonnespeech.html</a>Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0tag:blogger.com,1999:blog-6747067.post-1081870420062433672004-04-13T08:32:00.000-07:002004-06-01T22:07:43.846-07:00DateTime formatting and best practices<a href="http://msdn.microsoft.com/netframework/default.aspx?pull=/library/en-us/dndotnet/html/datetimecode.asp">http://msdn.microsoft.com/netframework/default.aspx?pull=/library/en-us/dndotnet/html/datetimecode.asp</a>Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0tag:blogger.com,1999:blog-6747067.post-1081816773985731442004-04-12T17:38:00.000-07:002004-06-01T22:02:10.823-07:00Do I use Load, LoadFile, or LoadFrom?From Suzzanne Cook's blog:
<br /><a href="http://blogs.gotdotnet.com/suzcook/PermaLink.aspx/53e2a77b-9ff1-4ff6-b19d-131b01f58b4b">http://blogs.gotdotnet.com/suzcook/PermaLink.aspx/53e2a77b-9ff1-4ff6-b19d-131b01f58b4b</a>Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.comtag:blogger.com,1999:blog-6747067.post-1081816481907042572004-04-12T17:36:00.000-07:002004-06-01T22:08:07.530-07:00Any given Monday?I was recently tasked with finding out the calendar date of of the first day of any week. I came up with the following code:
<br />
<br /><code>
<br /> DateTime GetFirstDayOfWeekDate(DateTime reference, DateTimeFormatInfo dtfi)
<br /> {
<br />   Calendar cal = dtfi.Calendar;
<br />   DayOfWeek dow = cal.GetDayOfWeek(reference);
<br />   DateTime firstDayOfWeek = dtReference.AddDays((((int)dtfi.FirstDayOfWeek - (int)dow) - 7) % 7);
<br />   return firstDayOfWeek;
<br /> }
<br /></code>
<br />I have run it through a test that uses all 7 days as the first day of the week and calculates the date for 10,000 days. Upon spot checks of the results it seems to work. I have only tested it with the EN-us culture. I don't know how it works with other cultures.
<br />
<br />Does anyone know of a different\better way or see any problems with this?Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0tag:blogger.com,1999:blog-6747067.post-1081816300274400562004-04-12T17:28:00.000-07:002004-06-01T22:08:33.333-07:00Using SQL bigint in your applicationsYou can use SQL bigint in your applications but be careful that you use the appropriate integer size in your code. For a quick reference see the following list:
<br />
<br />SQL bigint = 9223372036854775808
<br />XSD unsignedLong = 18446744073709551615
<br />.NET ulong = 18446744073709551615Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0tag:blogger.com,1999:blog-6747067.post-1081815807115016842004-04-12T17:23:00.000-07:002004-06-01T22:08:59.336-07:00ReleaseComObjectChris Brumme to the rescue again...
<br />
<br /><a href="http://blogs.gotdotnet.com/cbrumme/commentview.aspx/940d1191-3cc5-4b8d-a8b3-68b47f2f8dcb">http://blogs.gotdotnet.com/cbrumme/commentview.aspx/940d1191-3cc5-4b8d-a8b3-68b47f2f8dcb</a>Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0tag:blogger.com,1999:blog-6747067.post-1081815759351270252004-04-12T17:22:00.000-07:002004-06-01T22:09:21.680-07:00Side-by-side execution in .NETGood overview of side-by-side execution.
<br />
<br /><a href="http://www.3leaf.com/resources/articles/sbs.aspx">http://www.3leaf.com/resources/articles/sbs.aspx</a>Anonymoushttp://www.blogger.com/profile/11986207138920842170noreply@blogger.com0