<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>James Nachbar's Blog</title>
	<atom:link href="http://nachbar.name/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://nachbar.name/blog</link>
	<description>Programming and Plastic Surgery</description>
	<lastBuildDate>Mon, 28 Jun 2010 02:31:16 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>DevArt.com UniDAC in C++ Builder 2010 to access SQL Server Compact Edition</title>
		<link>http://nachbar.name/blog/2010/06/07/devart-com-unidac-in-c-builder-2010-to-access-sql-server-compact-edition/</link>
		<comments>http://nachbar.name/blog/2010/06/07/devart-com-unidac-in-c-builder-2010-to-access-sql-server-compact-edition/#comments</comments>
		<pubDate>Tue, 08 Jun 2010 03:09:09 +0000</pubDate>
		<dc:creator>nachbar</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[SQL Server Compact Edition]]></category>
		<category><![CDATA[VCL]]></category>
		<category><![CDATA[cb2010]]></category>

		<guid isPermaLink="false">http://nachbar.name/blog/?p=108</guid>
		<description><![CDATA[Use DevArt.com's UniDAC VCL components to access SQL Server Compact Edition from C++ Builder, working around the bugs in the UniDAC package that prevent C++ Builder projects from compiling.]]></description>
			<content:encoded><![CDATA[<p>DevArt makes a number of data access products for Delphi/C++ Builder as well as .NET .  I downloaded a trial of the UniDAC Universal Data Access Components for VCL.  Unfortunately, the documentation is sparse, to say the least, and C++ builder choked on compiling even a very simple application.  Here are a few notes on getting this working to access SQL Server Compact Edition (SQL CE).</p>
<p>Also unfortunately, Microsoft seems to have left a glaring (and even actually hard to believe) defect in its product line by not including any ability to transfer data to or from SQL Server (or any other database) and SQL Server Compact Edition.  Thus, I wrote a small utility to transfer my data into SQL CE.</p>
<p>The only code I could find on DevArt&#8217;s website for accessing SQL CE was for Delphi rather than for C++ Builder.  However, the following works to access SQL CE and read a list of tables:</p>
<p><code><br />
UniConnection1->SpecificOptions->Values["OLEDBProvider"] = "prCompact";<br />
UniConnection1->Database = "C:\\work\\VS2010Tests\\CreatedDB01.sdf";<br />
UniConnection1->Connect();<br />
TStrings* list = new TStringList();<br />
UniConnection1->GetTableNames(list, true);<br />
ListBox1->Items->Assign(list);<br />
</code></p>
<p>You add a TUniConnection to the form, and then you must set ProviderName in the TUniConnection to &#8216;SQL Server&#8217; in the property combo box to avoid the EDatabaseError <strong>&#8216;Provider is not defined&#8217;.</strong></p>
<p>However, C++ Builder will still fail to link the project with the error <strong> [ILINK32 Error] Fatal: Unable to open file &#8216;SQLSERVERUNIPROVIDER.OBJ&#8217;</strong>  Apparently the fix for that is to manually edit your .cbproj project file (!), find the <AllPackageLibs> element, and add <strong>msprovider140.lib</strong></p>
<p>Now, your project will compile and fill the listbox with the list of tables!</p>
]]></content:encoded>
			<wfw:commentRss>http://nachbar.name/blog/2010/06/07/devart-com-unidac-in-c-builder-2010-to-access-sql-server-compact-edition/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using external SATA / eSATA hard drive with Scientific Atlanta EXPLORER 8300 and 8300HD DVRs from COX</title>
		<link>http://nachbar.name/blog/2010/02/17/using-external-sata-esata-hard-drive-with-scientific-atlanta-explorer-8300-dvr-from-cox/</link>
		<comments>http://nachbar.name/blog/2010/02/17/using-external-sata-esata-hard-drive-with-scientific-atlanta-explorer-8300-dvr-from-cox/#comments</comments>
		<pubDate>Thu, 18 Feb 2010 06:13:26 +0000</pubDate>
		<dc:creator>nachbar</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[DVR]]></category>
		<category><![CDATA[eSATA]]></category>
		<category><![CDATA[Explorer 8300]]></category>
		<category><![CDATA[external drive]]></category>
		<category><![CDATA[PH3100U-1EXB]]></category>
		<category><![CDATA[SATA]]></category>
		<category><![CDATA[Scientific Atlanta]]></category>
		<category><![CDATA[Toshiba]]></category>

		<guid isPermaLink="false">http://nachbar.name/blog/?p=95</guid>
		<description><![CDATA[The hard drive that worked was the Toshiba PH3100U-1EXB 1 terabyte external hard drive (available right now at Fry&#8217;s Electronics for $99!)  The one that did not work was a two terabyte dual drive raid external hard drive of a different brand.
A friend has a Scientific Atlanta EXPLORER 8300 DVR rented from COX Communications [...]]]></description>
			<content:encoded><![CDATA[<p><strong>The hard drive that worked was the Toshiba PH3100U-1EXB 1 terabyte external hard drive (available right now at Fry&#8217;s Electronics for $99!)</strong>  The one that did not work was a two terabyte dual drive raid external hard drive of a different brand.</p>
<p>A friend has a Scientific Atlanta EXPLORER 8300 DVR rented from COX Communications in Arizona.  It has a fairly small amount of storage (about 74 GB, according to the info &#8211; see below), and has an external connector labeled &#8220;SATA&#8221;.  I Googled it, and it looks like some people have had success adding an external hard drive.  However, details as to which drives worked and didn&#8217;t work are hard to come by.  I couldn&#8217;t find anything on Scientific Atlanta&#8217;s website (apparently now part of Cisco), and when I called COX, the tech said to call Scientific Atlanta myself, since COX doesn&#8217;t support adding an external hard drive and didn&#8217;t know how to do it (an uncharacteristically poor customer support experience for COX, which has usually had excellent customer support in my experience).</p>
<p>I went to Fry&#8217;s electronics, and they said I needed some sort of &#8220;media extender&#8221;, which they didn&#8217;t have.  They said that using an eSATA drive was hit and miss.  So I missed and then I hit.  I wanted to report my experience to save others the trouble.  </p>
<p>I am not customer support for either COX or Scientific Atlanta/CISCO.  I don&#8217;t know if this will work for others, and I don&#8217;t know what other combinations might work.  I take absolutely no responsibility for any damage you may do by repeating my experience.  There is at least some chance that you will lose any recordings you have, so if that is a concern, be sure to watch and/or copy them elsewhere (although I lost no recordings).  However, if you find other combinations that work, with this or other DVR&#8217;s, please post your findings in the comments below.</p>
<p>First, and most important, check to see whether you have an eSATA or a SATA connector.  In my case, it was an eSATA connector labeled &#8220;SATA&#8221;.  Look online for pictures of the difference.  The SATA connectors have an &#8220;elbow&#8221; inside that the eSATA does not have.  You can use a digital camera to take a detailed close-up if needed.</p>
<p>Second, you will need an external hard drive with an eSATA connector (most only have USB or perhaps Firewire connectors).  You also need to purchase the cable to connect the eSATA connector on your drive to the eSATA connector on the 8300.  Different eSATA cables have different connectors, so be sure to get the right one.</p>
<p>To connect the drive, first turn the 8300 off, then unplug it for at least 15 seconds.  Be sure both the drive and the 8300 are unplugged, and connect the eSATA cable between them.  Leave the drive unplugged, but plug the 8300 back in.  It will go through its boot sequence, then the panel on the front of the 8300 will go black.  You then have to wait for it to get a signal from the cable company, and the time will then come on the screen.  That may take five or ten minutes.</p>
<p>Once the 8300 has the time showing, turn on the 8300 and the TV so you are watching TV through the 8300.  Now, plug in the drive, and if needed, turn on the switch so the light on the drive comes on.  Now comes the moment of truth.</p>
<p>The first time I did this, I got a message on the TV that the drive or cable were working improperly.  I had to press a button on the remote to dismiss the message, and was informed that the external storage will not be working.  You should check the cable, but in my case, after several tries, I always got the same message.  Unplug everything and disconnect your drive.  Fortunately, Fry&#8217;s Electronics has a great return policy!</p>
<p>The second time I did this, success!  When I turned on the drive, I got a message that the drive would have to be formatted, and I would lose all information on the drive, including any saved recordings.  I pressed the button to proceed.  There was no indication that anything was happening, and the 8300 continued to work as normal.  I left it running for about 40 minutes, to give plenty of time for formatting, although I don&#8217;t really know how long formatting takes.  After 40 minutes, still no indication of progress, and the 8300 indicated that its storage was as full as it has ever been.</p>
<p>So after 40 minutes, I unplugged the 8300 again for 15 seconds, and plugged it back in to reboot the 8300.  After it came back up, I turned it on with the remote.  I left for a while, and when I came back the 8300 would only play PBS, and attempts to change the channel or bring up the list of saved programs did not work.  I wasn&#8217;t sure what was going on, so after a little while I unplugged the 8300 again, disconnected the external drive, and plugged the 8300 back in again.  I then saw a message about advanced functions temporarily not working even with the external drive disconnected, and again I could only watch PBS.  Therefore, I unplugged the 8300 again, again connected the eSATA cable to the external drive, plugged in the external drive, and plugged in the 8300, and just left it alone for a while.  About an hour later, I went back, turned on the 8300 with the remote, and the 8300 was working normally, except that the available space had increased dramatically (95% full went to 6% full)!  All of the saved programs were still there, but there was a lot more empty space.</p>
<p>Next time, once the external drive was formatted, I would unplug the 8300 for 15 seconds, leave the external drive plugged in, and then plug the 8300 back in, and leave it alone for an hour.</p>
<p><strong>Update for the 8300HD:</strong>  I tried the same thing for a 8300HD unit.  I unplugged the 8300HD for 15 seconds, connected the external drive (a different specimen of the same model), plugged in only the 8300HD (not the drive) until the time showed on the 8300HD, used the remote to turn on the 8300HD so I was viewing the 8300HD&#8217;s signal through the TV, then plugged in the drive and pushed the on button on the drive.  The light on the drive came on, and I got the dialog asking me whether to &#8220;Format this external storage device to work with this DVR?&#8221;.  I pressed the &#8220;A&#8221; key for &#8220;Yes, Format&#8221;.  The dialog disappeared, and there was little or no indication that anything was happening.  After about five minutes of nothing, including no flashing of the light on the drive, I again unplugged the 8300HD for 15 seconds, and plugged it back in.  After the time showed on the 8300HD, I turned on the 8300HD with the remote, and got a message box that said: &#8220;The external storage device connected works with this DVR.  NOTE: To safely unplug this device, first unplug power from the DVR, then wait 10 seconds before disconnecting.&#8221;  After about 10 seconds, that message box disappeared, and the DVR worked normally, but had a lot more empty space!  <strong>So, on the 8300HD, the whole process only took about 15 minutes.</strong></p>
<p><strong>Update for the Explorer 8240HD</strong>  The original 8300 was replaced with an 8240HD, for high definition.  The hard drive that was used with the 8300 originally was disconnected after unplugging the 8300 for 15 seconds.  It was moved to the new 8240HD, and hooked up with the same result as with the 8300HD above.  Note that, since the hard drive does not come on until its button is pushed, if there is a power failure, someone will have to push the on button for the hard drive for it to work again.  I tested to see what happens if the button is not pushed until after the 8240HD turned on, and the only notable effect was that there was less space available on the 8240HD.  When the drive was turned on, I again got the message the the external storage works with this DVR.  The 8240HD has a 148 GB disk installed, and I added 931 GB (according to the info page) with the new disk.</p>
<p>The old 8300 appears to be confused about how much space is available now, showing a screen indicating that there is still as much space as there was before.  Many of the recorded shows are still in the list, but as expected, trying to play them does not work, but rather the DVR goes right to the &#8220;Press the list button to see your recordings&#8221; screen.</p>
<p>Reviewing postings on the Internet, I would be careful to be sure that the 8300 is unplugged prior to allowing the external drive to lose power or be disconnected, for fear of data corruption and/or loss of all your recordings.  Also, the recordings on the drive are reportedly encrypted with a key that is specific to the serial number of your 8300, so if the drive is moved to another box, you will not be able to view the recordings there.</p>
<p>To see info about your 8300, including info about the attached internal and external drives and what interfaces have been enabled by COX, use the keys on the front of the 8300.  Press and hold the &#8220;SELECT&#8221; button until the little flashing mail icon comes on, then release the &#8220;SELECT&#8221; button and press the &#8220;INFO&#8221; button.  Page forward and back with the Volume + and Volume &#8211; buttons.  Press the &#8220;EXIT&#8221; button when you are done.</p>
<p>If you have success with other DVR&#8217;s and/or drives or have other experiences, please let me know in the comments!</p>
]]></content:encoded>
			<wfw:commentRss>http://nachbar.name/blog/2010/02/17/using-external-sata-esata-hard-drive-with-scientific-atlanta-explorer-8300-dvr-from-cox/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Using IMallocSpy to check for BSTR memory leaks in Embarcadero C++ Builder CB2009</title>
		<link>http://nachbar.name/blog/2009/10/04/imallocspy-for-bstr-memory-leaks-embarcadero-c-builder-cb2009/</link>
		<comments>http://nachbar.name/blog/2009/10/04/imallocspy-for-bstr-memory-leaks-embarcadero-c-builder-cb2009/#comments</comments>
		<pubDate>Sun, 04 Oct 2009 17:20:07 +0000</pubDate>
		<dc:creator>nachbar</dc:creator>
				<category><![CDATA[cb2009]]></category>

		<guid isPermaLink="false">http://nachbar.name/blog/?p=90</guid>
		<description><![CDATA[IMallocSpy is a COM interface provided to check for memory leaks using the IMalloc interface, as used in allocating BSTR&#8217;s.  I was recently trying to figure out which CB2009 objects would release the returned BSTR, so I looked for a way to test for memory leaks.  I found this reference for using IMallocSpy [...]]]></description>
			<content:encoded><![CDATA[<p>IMallocSpy is a COM interface provided to check for memory leaks using the IMalloc interface, as used in allocating BSTR&#8217;s.  I was recently trying to figure out which CB2009 objects would release the returned BSTR, so I looked for a way to test for memory leaks.  I found this reference for using IMallocSpy using the Microsoft tools <a href="http://comcorba.tripod.com/comleaks.htm" target="_blank">http://comcorba.tripod.com/comleaks.htm</a> , but could not find it adapted for CB2009.  Here is my adaptation for CB2009.</p>
<p>The answer to my original question:</p>
<p><code><br />
OleVariant var = node->GetAttribute("xmlns"); // this DOES NOT cause a memory leak = OleVariant takes control of the BSTR, and then frees it<br />
UnicodeString str = (wchar_t*)node->GetAttribute("xmlns"); // this DOES cause a memory leak<br />
WideString ws = node->GetAttribute("xmlns"); // this DOES NOT cause a memory leak<br />
WideString nws = node->GetAttribute("nonesuch"); // this returns a NULL, which throws an exception<br />
</code></p>
<p>If the attribute might not exist and you don&#8217;t want to throw an exception, you can use:</p>
<p><code><br />
String str;<br />
OleVariant val = subNode->Attributes[desiredSubAttribute];<br />
if (!val.IsNull())<br />
  str = val;<br />
</code></p>
<p>Here is the code to implement the IMallocSpy tester.  It allocates an array to keep track of IMalloc allocations and deallocations, and then dumps its output with OutputDebugString when requested.  For details, see the link above.  Again, the code below is ported from the example code at <a href="http://comcorba.tripod.com/comleaks.htm" target="_blank">comcorba.tripod.com</a> by Jason Pritchard.</p>
<p>As noted, do NOT include this code in software sent to a customer.  It is for testing only.</p>
<p><code><br />
//	Need to call SetOaNoCache to turn off the BSTR Cache, or else we will ALWAYS report leaks</p>
<p>typedef void WINAPI (*SETOANOCACHE)();</p>
<p>HINSTANCE hDLL = LoadLibrary(L"oleaut32.dll");<br />
if (!hDLL)<br />
	throw Exception("Unable to load oleaut32.dll");</p>
<p>SETOANOCACHE SetOaNoCachePtr = (SETOANOCACHE) GetProcAddress(hDLL, "SetOaNoCache");<br />
if (!SetOaNoCachePtr) {<br />
	throw Exception("Unable to get SetOaNoCache");<br />
}<br />
SetOaNoCachePtr();</p>
<p>	// Initialize COM.<br />
	::CoInitialize(NULL);</p>
<p>	// Initialize the COM memory checker ...<br />
	CMallocSpy* pMallocSpy = new CMallocSpy;<br />
	pMallocSpy->AddRef();<br />
	::CoRegisterMallocSpy(pMallocSpy);</p>
<p>	pMallocSpy->Clear();</p>
<p>	// pMallocSpy->SetBreakAlloc(4);  // enable this if you want the debugger to break at COM allocation 4</p>
<p>	test_com_allocs(); // run your test allocations and deallocations - e.g. the test code above</p>
<p>	// Dump COM memory leaks<br />
	pMallocSpy->Dump();</p>
<p>	// Unregister the malloc spy ...<br />
	::CoRevokeMallocSpy();<br />
	pMallocSpy->Release();<br />
	::CoUninitialize();<br />
</code></p>
<p>The COM memory checker object:</p>
<p><code><br />
// IMallocSpyUnit.h<br />
class CMallocSpy : public IMallocSpy<br />
{<br />
public:<br />
	CMallocSpy(void);<br />
	~CMallocSpy(void);</p>
<p>	// IUnknown methods<br />
			virtual HRESULT STDMETHODCALLTYPE QueryInterface(<br />
				/* [in] */ REFIID riid,<br />
				/* [iid_is][out] */ __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject);</p>
<p>			virtual ULONG STDMETHODCALLTYPE AddRef( void);</p>
<p>			virtual ULONG STDMETHODCALLTYPE Release( void);</p>
<p>    // IMallocSpy methods<br />
		virtual SIZE_T STDMETHODCALLTYPE PreAlloc(<br />
			/* [in] */ SIZE_T cbRequest);</p>
<p>		virtual void *STDMETHODCALLTYPE PostAlloc(<br />
			/* [in] */ void *pActual);</p>
<p>		virtual void *STDMETHODCALLTYPE PreFree(<br />
			/* [in] */ void *pRequest,<br />
			/* [in] */ BOOL fSpyed);</p>
<p>		virtual void STDMETHODCALLTYPE PostFree(<br />
			/* [in] */ BOOL fSpyed);</p>
<p>		virtual SIZE_T STDMETHODCALLTYPE PreRealloc(<br />
			/* [in] */ void *pRequest,<br />
			/* [in] */ SIZE_T cbRequest,<br />
			/* [out] */ void **ppNewRequest,<br />
			/* [in] */ BOOL fSpyed);</p>
<p>		virtual void *STDMETHODCALLTYPE PostRealloc(<br />
			/* [in] */ void *pActual,<br />
			/* [in] */ BOOL fSpyed);</p>
<p>		virtual void *STDMETHODCALLTYPE PreGetSize(<br />
			/* [in] */ void *pRequest,<br />
			/* [in] */ BOOL fSpyed);</p>
<p>		virtual SIZE_T STDMETHODCALLTYPE PostGetSize(<br />
			/* [in] */ SIZE_T cbActual,<br />
			/* [in] */ BOOL fSpyed);</p>
<p>		virtual void *STDMETHODCALLTYPE PreDidAlloc(<br />
			/* [in] */ void *pRequest,<br />
			/* [in] */ BOOL fSpyed);</p>
<p>		virtual int STDMETHODCALLTYPE PostDidAlloc(<br />
			/* [in] */ void *pRequest,<br />
			/* [in] */ BOOL fSpyed,<br />
			/* [in] */ int fActual);</p>
<p>		virtual void STDMETHODCALLTYPE PreHeapMinimize( void);</p>
<p>		virtual void STDMETHODCALLTYPE PostHeapMinimize( void);</p>
<p>	// Utilities ...</p>
<p>	void Clear();<br />
	void Dump();<br />
	void SetBreakAlloc(int allocNum);</p>
<p>protected:<br />
	enum<br />
	{<br />
		HEADERSIZE = 4,<br />
		MAX_ALLOCATIONS = 100000   // cannot handle more than max<br />
	};</p>
<p>    ULONG   m_cRef;<br />
    ULONG   m_cbRequest;<br />
	int     m_counter;<br />
    int     m_breakAlloc;<br />
    char   *m_map;<br />
    size_t  m_mapSize;<br />
};</p>
<p>// IMallocSpyUnit.cpp<br />
#include <comdef.h> // for IUnknown, IMallocSpy, etc.<br />
#include "IMallocSpyUnit.h"</p>
<p>#pragma package(smart_init)</p>
<p>// Constructor/Destructor</p>
<p>CMallocSpy::CMallocSpy(void)<br />
{<br />
    m_cRef = 0;<br />
    m_counter = 0;<br />
    m_mapSize = MAX_ALLOCATIONS;<br />
    m_map = new char[m_mapSize];<br />
    memset(m_map, 0, m_mapSize);<br />
}</p>
<p>CMallocSpy::~CMallocSpy(void)<br />
{<br />
    delete [] m_map;<br />
}</p>
<p>// IUnknown support ...</p>
<p>			HRESULT STDMETHODCALLTYPE CMallocSpy::QueryInterface(<br />
				/* [in] */ REFIID riid,<br />
				/* [iid_is][out] */ __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppUnk)<br />
{<br />
	HRESULT hr = S_OK;<br />
	if (IsEqualIID(riid, IID_IUnknown))<br />
	{<br />
		*ppUnk = (IUnknown *) this;<br />
	}<br />
	else if (IsEqualIID(riid, IID_IMallocSpy))<br />
    {<br />
        *ppUnk =  (IMalloc *) this;<br />
    }<br />
    else<br />
    {<br />
        *ppUnk = NULL;<br />
        hr =  E_NOINTERFACE;<br />
    }</p>
<p>    AddRef();<br />
    return hr;<br />
}</p>
<p>ULONG STDMETHODCALLTYPE CMallocSpy::AddRef( void)<br />
{<br />
	return ++m_cRef;<br />
}</p>
<p>ULONG STDMETHODCALLTYPE CMallocSpy::Release(void)<br />
{<br />
    ULONG cRef;<br />
    cRef = --m_cRef;<br />
    if (cRef == 0)<br />
    {<br />
        delete this;<br />
    }</p>
<p>    return cRef;<br />
}</p>
<p>// Utilities ...<br />
void CMallocSpy::SetBreakAlloc(int allocNum)<br />
{<br />
    m_breakAlloc = allocNum;<br />
}</p>
<p>void CMallocSpy::Clear()<br />
{<br />
    memset(m_map, 0, m_mapSize);<br />
}</p>
<p>void CMallocSpy::Dump()<br />
{<br />
    char buff[256];<br />
    ::OutputDebugString("CMallocSpy dump ->\n");<br />
    for (int i=0; i <= m_counter; i++)<br />
    {<br />
		if (m_map[i] != 0)<br />
		{<br />
			sprintf(buff, " IMalloc memory leak at [%d]\n", i);<br />
			::OutputDebugString(buff);<br />
		}<br />
	}<br />
    ::OutputDebugString("CMallocSpy dump complete.\n");<br />
}</p>
<p>// IMallocSpy methods ...<br />
SIZE_T STDMETHODCALLTYPE CMallocSpy::PreAlloc(<br />
			/* [in] */ SIZE_T cbRequest)<br />
{<br />
    m_cbRequest = cbRequest;<br />
    return cbRequest + HEADERSIZE;<br />
}</p>
<p>void *STDMETHODCALLTYPE CMallocSpy::PostAlloc(<br />
			/* [in] */ void *pActual)<br />
{<br />
    m_counter++;<br />
    if (m_breakAlloc == m_counter)<br />
        ::DebugBreak();<br />
    // Store the allocation counter and note that this allocation is active in the map.<br />
    memcpy(pActual, &#038;m_counter, 4);<br />
    m_map[m_counter] = 1;<br />
    return (void*)((BYTE*)pActual + HEADERSIZE);<br />
}</p>
<p>void *STDMETHODCALLTYPE CMallocSpy::PreFree(<br />
			/* [in] */ void *pRequest,<br />
			/* [in] */ BOOL fSpyed)<br />
{<br />
    if (pRequest == NULL)<br />
        return NULL;</p>
<p>    if (fSpyed)<br />
    {<br />
        // Mark the allocation as inactive in the map.<br />
        int counter;<br />
        pRequest = (void*)(((BYTE*)pRequest) - HEADERSIZE);<br />
        memcpy(&#038;counter, pRequest, 4);<br />
        m_map[counter] = 0;<br />
        return pRequest;<br />
    }<br />
    else<br />
        return pRequest;<br />
}</p>
<p>void STDMETHODCALLTYPE CMallocSpy::PostFree(<br />
			/* [in] */ BOOL fSpyed)<br />
{<br />
    return;<br />
}</p>
<p>SIZE_T STDMETHODCALLTYPE CMallocSpy::PreRealloc(<br />
			/* [in] */ void *pRequest,<br />
			/* [in] */ SIZE_T cbRequest,<br />
			/* [out] */ void **ppNewRequest,<br />
			/* [in] */ BOOL fSpyed)<br />
{<br />
	if (fSpyed  &#038;&#038;  pRequest != NULL)<br />
	{<br />
		// Mark the allocation as inactive in the map since IMalloc::Realloc()<br />
		// frees the originally allocated block.<br />
		int counter;<br />
		BYTE* actual = (BYTE*)pRequest - HEADERSIZE;<br />
		memcpy(&#038;counter, actual, 4);<br />
		m_map[counter] = 0;<br />
		*ppNewRequest = (void*)(((BYTE*)pRequest) - HEADERSIZE);<br />
		return cbRequest + HEADERSIZE;<br />
	}<br />
	else<br />
	{<br />
		*ppNewRequest = pRequest;<br />
		return cbRequest;<br />
	}<br />
}</p>
<p>void *STDMETHODCALLTYPE CMallocSpy::PostRealloc(<br />
			/* [in] */ void *pActual,<br />
			/* [in] */ BOOL fSpyed)<br />
{<br />
	if (fSpyed)<br />
	{<br />
		m_counter++;<br />
        if (m_breakAlloc == m_counter)<br />
            ::DebugBreak();</p>
<p>        // Store the allocation counter and note that this allocation<br />
        // is active in the map.<br />
		memcpy(pActual, &#038;m_counter, 4);<br />
        m_map[m_counter] = 1;<br />
        return (void*)((BYTE*)pActual + HEADERSIZE);<br />
    }<br />
    else<br />
        return pActual;</p>
<p>}</p>
<p>void *STDMETHODCALLTYPE CMallocSpy::PreGetSize(<br />
			/* [in] */ void *pRequest,<br />
			/* [in] */ BOOL fSpyed)<br />
{<br />
    if (fSpyed)<br />
        return (void *) (((BYTE *) pRequest) - HEADERSIZE);<br />
    else<br />
        return pRequest;<br />
}</p>
<p>SIZE_T STDMETHODCALLTYPE CMallocSpy::PostGetSize(<br />
			/* [in] */ SIZE_T cbActual,<br />
			/* [in] */ BOOL fSpyed)<br />
{<br />
	if (fSpyed)<br />
        return cbActual - HEADERSIZE;<br />
    else<br />
        return cbActual;<br />
}</p>
<p>void *STDMETHODCALLTYPE CMallocSpy::PreDidAlloc(<br />
			/* [in] */ void *pRequest,<br />
			/* [in] */ BOOL fSpyed)<br />
{<br />
	if (fSpyed)<br />
        return (void *) (((BYTE *) pRequest) - HEADERSIZE);<br />
    else<br />
        return pRequest;<br />
}</p>
<p>int STDMETHODCALLTYPE CMallocSpy::PostDidAlloc(<br />
			/* [in] */ void *pRequest,<br />
			/* [in] */ BOOL fSpyed,<br />
			/* [in] */ int fActual)<br />
{<br />
    return fActual;<br />
}</p>
<p>void STDMETHODCALLTYPE CMallocSpy::PreHeapMinimize( void)<br />
{<br />
	return;<br />
}</p>
<p>void STDMETHODCALLTYPE CMallocSpy::PostHeapMinimize( void)<br />
{<br />
    return;<br />
}<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://nachbar.name/blog/2009/10/04/imallocspy-for-bstr-memory-leaks-embarcadero-c-builder-cb2009/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Embarcadero C++ Builder &#8211; Sending UnicodeString via COM truncates string to half</title>
		<link>http://nachbar.name/blog/2009/10/04/embarcadero-c-builder-sending-unicodestring-via-com-truncates-string-to-half/</link>
		<comments>http://nachbar.name/blog/2009/10/04/embarcadero-c-builder-sending-unicodestring-via-com-truncates-string-to-half/#comments</comments>
		<pubDate>Sun, 04 Oct 2009 16:21:06 +0000</pubDate>
		<dc:creator>nachbar</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://nachbar.name/blog/?p=85</guid>
		<description><![CDATA[CB2009 defines a BSTR as a wchar_t*, which is the type returned by c_str() when UNICODE is set.  Therefore, if you call a COM function which expects a BSTR with UnicodeString.c_str(), the compiler returns the wchar_t* which the function expects.  Sounds good!  Except it doesn&#8217;t work!!
Actually, both BSTR and the character array [...]]]></description>
			<content:encoded><![CDATA[<p>CB2009 defines a BSTR as a wchar_t*, which is the type returned by c_str() when UNICODE is set.  Therefore, if you call a COM function which expects a BSTR with UnicodeString.c_str(), the compiler returns the wchar_t* which the function expects.  Sounds good!  Except it doesn&#8217;t work!!</p>
<p>Actually, both BSTR and the character array in UnicodeString prefix the array of wide chars with a four-byte integer that gives the length.  However, BSTR expects this to be the length IN BYTES, whereas UnicodeString makes this the length IN CHARACTERS.  Thus, the server gets the wchar_t*, looks right before the pointer for an int, and only uses that many bytes.  So, if your UnicodeString is seven chars long, and thus 14 bytes long, CB2009 sets the length to seven, and COM only accepts the first seven bytes (and thus the first four chars).  So, all your strings are cut in half!</p>
<p>To make things worse, UnicodeString.Length() does not count out the length to the null terminating char, but rather just returns the integer.  So, if you fix the integer to be 14 as COM expects, UnicodeString.Length now returns 14 for your seven character string!  We dare not mess with UnicodeString&#8217;s data.</p>
<p>The solution is to use WideString instead.  Instead of:</p>
<p>UnicodeString myString = L&#8221;My Data&#8221;;<br />
ptr-&gt;ComFunctionExpectingBSTR(myString.c_str()); // this compiles, but COM only uses the first half of the string</p>
<p>use</p>
<p>UnicodeString myString = L&#8221;My Data&#8221;;<br />
ptr-&gt;ComFunctionExpectingBSTR(WideString(myString).c_bstr()); // this has the correct length</p>
<p>References:<br />
<a href="http://msdn.microsoft.com/en-us/library/ms221069.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/ms221069.aspx</a> &#8211; Microsoft&#8217;s reference for the BSTR type in MSDN/Win32 and COM Development/Component Development/COM/Automation Programming Reference/Data Types, Structures and Enumerations/IDispatch Data Types and Structures</p>
<p><a href="http://docwiki.embarcadero.com/RADStudio/en/Unicode_in_RAD_Studio#New_String_Type:_UnicodeString" target="_blank">http://docwiki.embarcadero.com/RADStudio/en/Unicode_in_RAD_Studio#New_String_Type:_UnicodeString</a> &#8211; Unicode in RAD Studio</p>
<p>NOTE:  In my testing, this is a problem sending data to Microsoft Outlook 2007.  It did not appear to cause a problem when sending to Crystal Reports, so the issue might well be with the server code rather than the COM subsystem, depending on how the server determines the length of the passed string.  I have seen example code that just passes a WideString to COM, but for me, the compiler gives a Type mismatch error unless I pass the pointer returned by c_bstr()</p>
<p>To see how the length of the string is set:<br />
<code><br />
wchar_t* lit = L"My Sttring";<br />
int* litIPtr = (int*) lit;<br />
litIPtr--;<br />
int litLen = *litIPtr;</code></p>
<p><code>WideString ws = lit;<br />
wchar_t* wsPtr = ws.c_bstr();<br />
int* wsIPtr = (int*) wsPtr;<br />
wsIPtr--;<br />
int wsLen = *wsIPtr;</code></p>
<p><code>UnicodeString us =  lit;<br />
wchar_t* usPtr = us.c_str();<br />
int* usIPtr = (int*) usPtr;<br />
usIPtr--;<br />
int usLen = *usIPtr;</p>
<p>// int actualLen = StrLen(lit);   // if UNICODE is set<br />
int actualLen = wcslen(lit);</p>
<p></code></p>
<p><code> ShowMessage("For a " + String(actualLen) + " character string, Literal gives " +<br />
String(litLen) + ", WideString gives " +<br />
String(wsLen) + ", UnicodeString gives " + String(usLen));<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://nachbar.name/blog/2009/10/04/embarcadero-c-builder-sending-unicodestring-via-com-truncates-string-to-half/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows Communication Foundation 3.5 Unleashed Errors</title>
		<link>http://nachbar.name/blog/2009/06/14/windows-communication-foundation-35-unleashed-errors/</link>
		<comments>http://nachbar.name/blog/2009/06/14/windows-communication-foundation-35-unleashed-errors/#comments</comments>
		<pubDate>Sun, 14 Jun 2009 19:47:19 +0000</pubDate>
		<dc:creator>nachbar</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://nachbar.name/blog/?p=78</guid>
		<description><![CDATA[I am reading this book; it is very well written, and the people who wrote it are obviously very smart.  Unfortunately, it is chock full of technical errors.  I have wasted hours trying to get the examples to work.  In the hope of saving others some time, I am listing a few [...]]]></description>
			<content:encoded><![CDATA[<p>I am reading this book; it is very well written, and the people who wrote it are obviously very smart.  Unfortunately, it is chock full of technical errors.  I have wasted hours trying to get the examples to work.  In the hope of saving others some time, I am listing a few of the problems I found.</p>
<p>In addition to these, there are lots of other errors I found in my first, casual, reading, especially in the code.</p>
<p>In the Fundamentals chapter (2)</p>
<p>Page 45, step 1: add the app.config file to the Host project, NOT the DerivativesCalculatorService project (see page 53)<br />
error: <strong>Service &#8216;DerivativesCalculator.DerivativesCalculatorServiceType&#8217; has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element.</strong></p>
<p>Page 56, step 4: there should not be a colon before &#8220;svcutil&#8221; (and there is not in the screenshot below)</p>
<p>Page 58: The class should be DerivativesCalculatorClient rather than DerivativesCalculatorProxy (since that is the class created by the tool &#8212; see listing 2.6)</p>
<p>Page 67 &#8211; 72: Getting the service to run under IIS 7.0 required quite a number of additional steps, at least in my configuration.</p>
<p>1) &#8212; Page 69, Step 3 &#8211; Must use Add Application rather than Add Virtual Directory, at least in IIS 7.0 .  I wasted quite a bit of time on this one, until I found http://social.msdn.microsoft.com/forums/en-US/wcf/thread/49d9279f-2bc1-482b-8bb0-da1261736acb/ , where this exact problem with this exact same example was noted in April 2006.<br />
error: <strong>The type &#8216;DerivativesCalculatorService.Calculator&#8217;, provided as the Service attribute value in the ServiceHost directive could not be found.</strong></p>
<p>2) &#8212; Need to give the IIS_IUSRS permission to the DerivitivesCalculatorService directory, so IIS can use the config file</p>
<p>3) &#8212; Need to give the Anonamous Login user permission to the DeriviativesCalculatorService directory, so IIS will serve it to the user</p>
<p>4) &#8212; I had to fix the bindings to the .svc extension using<br />
c:\windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\ServiceModelReg -r<br />
It is possible that I had that problem because I enabled IIS after I had already installed VisualStudio.  Or not.</p>
<p>5) &#8212; I had to turn on the WCF Activation with Control Panel/Programs/Turn Windows Features On/Microsoft .NET 3.0/WCF Activation for http and non-http &#8211; see http://michael-arnett.spaces.live.com/blog/cns!5AA848FF3F707F99!1093.entry?<br />
- error: <strong>HTTP 500 &#8211; Handler svc-Integrated has a bad module “ManagedPipelineHandler” in its module list</strong></p>
<p>Page 75 &#8211; in my testing, the MSFT string was NOT encrypted when I used the netTcpBinding</p>
<p>Page 79 &#8211; to use the WcfTestClient with this demo, run:<br />
WcfTestClient http://localhost:8000/Derivatives/<br />
or<br />
WcfTestClient http://localhost:8000/Derivatives/?wsdl</p>
]]></content:encoded>
			<wfw:commentRss>http://nachbar.name/blog/2009/06/14/windows-communication-foundation-35-unleashed-errors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Neopost IJ25 Postage Meter Pricing Scam</title>
		<link>http://nachbar.name/blog/2009/03/23/neopost-ij25-postage-meter-pricing-scam/</link>
		<comments>http://nachbar.name/blog/2009/03/23/neopost-ij25-postage-meter-pricing-scam/#comments</comments>
		<pubDate>Tue, 24 Mar 2009 05:00:24 +0000</pubDate>
		<dc:creator>nachbar</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://nachbar.name/blog/?p=71</guid>
		<description><![CDATA[Neopost should be honest about the actual cost of renting their equipment, and not gouge their customers for the rate reprogramming and ink cartridges.  There is no excuse for charging $29 for overnight shipment of a 4 ounce cartridge.]]></description>
			<content:encoded><![CDATA[<p>I just got off the phone with Neopost, whose postage meter I have been using for a number of years.  I guess I never put together the true cost of using it.  The reason for my call was that my postage meter suddenly stopped working, saying &#8220;Warning, Ink Expired&#8221;.</p>
<p>It turns out that the Neopost IJ25 postage meter is programmed to stop working if the same ink cartridge has been installed for more than one year (as in 365 days).  When I called, I was told that we should have received a single warning about a month ago that the ink would expire soon.  However, if we had pushed &#8220;Ok&#8221; that one time, the warning would disappear, and the next warning would be when the postage meter stopped working altogether.  I don&#8217;t know if we got the warning or not, although nobody remembers seeing it.</p>
<p>Nonetheless, my Neopost IJ25 postage meter is dead in the water.  The cost for a replacement ink cartridge is $124: $86 for the cartridge (!!), $29 for overnight shipping &#8220;&#038; handling&#8221; (!!), and $9.32 for tax.  2-3 day shipping would have been $23, 10 day shipping $12.  Clearly, Neopost has a strong incentive to set up their IJ25 postage meter so we would not see the warning, and is not shy about overcharging for shipping.</p>
<p>In addition, Neopost gouges us to update the meter for postal rate changes (so it prints 43 cents instead of 42 cents) &#8211; this was $91.89 on 12/22/08, plus a special deal $67.02 for one year of subsequent updates.  In the notice, Neopost gleefully noted that the postal service has agreed to start increasing the postage more often &#8211; probably twice a year.  The thing is, to get the special deal, I have agreed to automatic, non-cancelable upgrades; to cancel, I must give at least 30 days, but no more than 60 days, notice.  Again, clearly designed to make it more difficult to cancel.</p>
<p>The only thing that is reasonably priced is the actual rental of the Neopost IJ25 postage meter and scale, at $219.57 for 12 months.</p>
<p>However, the actual cost of using the Neopost IJ25 meter for 12 months is: $219 rental, about $90 reprogramming, and $124 for the timed ink cartridge, or $433, or about twice the quoted rental cost.  Not to mention the inconvenience of having a postage meter that dies unexpectedly and with no (practical) notice.</p>
<p>So why is that a scam?  For the same reason that it is a scam when an airline quotes an airfare that doesn&#8217;t include baggage.  Neopost should be honest about the actual cost of renting their equipment, and not gouge their customers for the rate reprogramming and ink cartridges.  There is no excuse for charging $29 for overnight shipment of a 4 ounce cartridge.  And, worst of all, they should not design the Neopost IJ25 postage meter to fail unexpectedly and without (practical) warning, significantly inconveniencing their customer.</p>
<p>You can bet that between now and next December, I will be looking into other options that don&#8217;t include a meter programmed to fail.</p>
<p>If anyone from Neopost cares to dispute or comment on this post, I will be happy to talk with them.  If anything is incorrect, I will certainly correct it.</p>
]]></content:encoded>
			<wfw:commentRss>http://nachbar.name/blog/2009/03/23/neopost-ij25-postage-meter-pricing-scam/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Dreamweaver Secure FTP (SFTP) Configuration</title>
		<link>http://nachbar.name/blog/2009/03/01/dreamweaver-secure-ftp-sftp-configuration/</link>
		<comments>http://nachbar.name/blog/2009/03/01/dreamweaver-secure-ftp-sftp-configuration/#comments</comments>
		<pubDate>Mon, 02 Mar 2009 05:09:42 +0000</pubDate>
		<dc:creator>nachbar</dc:creator>
				<category><![CDATA[Dreamweaver]]></category>

		<guid isPermaLink="false">http://nachbar.name/blog/?p=60</guid>
		<description><![CDATA[Dreamweaver's Secure FTP is actually ssh!]]></description>
			<content:encoded><![CDATA[<p>The Dreamweaver configuration documentation for &#8220;Secure FTP&#8221; is poor to non-existant.  I am not talking about how to check Dreamweaver&#8217;s &#8220;Use Secure FTP (SFTP)&#8221; checkbox (which is trivial, but for which there is LOTS of documentation), but rather how to set up your secure server to receive the Secure FTP communication from Dreamweaver.</p>
<p>The trick is that Dreamweaver&#8217;s &#8220;Secure FTP&#8221; is not FTP!  It is ssh!  It runs on port 22, which is not configurable (within Dreamweaver, as of CS3).</p>
<p>So, for all of us who have wasted hours setting up an ftp server, and trying to figure out why Dreamweaver wouldn&#8217;t connect through the firewall, now you know!</p>
<p>You just have to set up sshd to receive connections on port 22, and don&#8217;t waste your time with vsftpd!</p>
<p>When configured properly, the (Ubuntu) /var/log/auth.log will report the connection via sshd, and sshd will report &#8220;subsystem request for sftp&#8221;.  sftp is an ftp-like program that runs under and through ssh.  You can read more about the sftp client via Linux &#8220;man sftp&#8221;.  You can use the sftp client to connect between Linux computers to transfer files over ssh like you would use ftp, but with no need to set up an ftp server (again, sftp uses the sshd server).</p>
]]></content:encoded>
			<wfw:commentRss>http://nachbar.name/blog/2009/03/01/dreamweaver-secure-ftp-sftp-configuration/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Ubuntu Server Configuration</title>
		<link>http://nachbar.name/blog/2009/03/01/ubuntu-server-configuration/</link>
		<comments>http://nachbar.name/blog/2009/03/01/ubuntu-server-configuration/#comments</comments>
		<pubDate>Sun, 01 Mar 2009 21:49:14 +0000</pubDate>
		<dc:creator>nachbar</dc:creator>
				<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://nachbar.name/blog/?p=57</guid>
		<description><![CDATA[A few random notes.
To start the iptables rules for the firewall on startup, first, create the firewall script, adding the iptables rules one by one, and save the rules with:

iptables-save > /etc/default/iptables

Then, to load the rules automatically with the new Upstart init system, I just create a new file, /etc/event.d/iptables :

# Script to start firewall
# [...]]]></description>
			<content:encoded><![CDATA[<p>A few random notes.</p>
<p>To start the iptables rules for the firewall on startup, first, create the firewall script, adding the iptables rules one by one, and save the rules with:</p>
<p><code><br />
iptables-save > /etc/default/iptables<br />
</code></p>
<p>Then, to load the rules automatically with the new Upstart init system, I just create a new file, /etc/event.d/iptables :</p>
<p><code><br />
# Script to start firewall<br />
# Save rules with iptables-save > /etc/default/iptables</p>
<p>start on runlevel 1<br />
start on runlevel 2<br />
start on runlevel 3<br />
start on runlevel 4<br />
start on runlevel 5</p>
<p>exec /sbin/iptables-restore < /etc/default/iptables<br />
</code></p>
<p>That way, you aren’t changing any existing files, just adding the new one. On every reboot, the iptables rules get loaded. You can check that they are loaded with:</p>
<p><code><br />
sudo /sbin/iptables-save | less<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://nachbar.name/blog/2009/03/01/ubuntu-server-configuration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iMovie &#8216;09 Error &#8211; Audio Exporting Problem</title>
		<link>http://nachbar.name/blog/2009/02/08/imovie-09-error-audio-exporting-problem/</link>
		<comments>http://nachbar.name/blog/2009/02/08/imovie-09-error-audio-exporting-problem/#comments</comments>
		<pubDate>Sun, 08 Feb 2009 16:42:16 +0000</pubDate>
		<dc:creator>nachbar</dc:creator>
				<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://nachbar.name/blog/?p=50</guid>
		<description><![CDATA[Apple recently updated its iLife suite (including iMovie) from &#8216;08 to &#8216;09.  I haven&#8217;t done much with movie creation, but wanted to make a short video demonstration of my 3 dimensional breast augmentation simulator.  We shot some video at the office.  I easily imported the tape into iMovie &#8216;08, but when I went to edit [...]]]></description>
			<content:encoded><![CDATA[<p>Apple recently updated its iLife suite (including iMovie) from &#8216;08 to &#8216;09.  I haven&#8217;t done much with movie creation, but wanted to make a short video demonstration of my 3 dimensional breast augmentation simulator.  We shot some video at the office.  I easily imported the tape into iMovie &#8216;08, but when I went to edit it, I noticed that iMovie &#8216;09, which had just been released, had two features I wanted: precision trimming, and the ability to slow down a clip.  So, I ordered the upgrade.  It came quickly, and installed easily.  About reports that it is version 8.0 (717).  Check for Updates reports that it is the current version.</p>
<p>I edited my video until I was happy with it.  iMovie crashed a couple of times, but did not lose any of my work.  I went to export the video into a format I could post.  That&#8217;s when my problems began!</p>
<p>On many of the clips, I had set the audio to zero, so I could use voiceover to explain them.  I also adjusted the speed so that I would have more time for my voiceover than the length of the clip.  In a  couple of places I added some simple transitions.</p>
<p>However, on the exported video, in one of the clips I could still hear the audio that had been recorded with the video, even though the volume was set to zero!  (Now, of course, the audio was very slow and sounded like a growling monster).  And on one of the other clips where I had not adjusted either the speed or the volume, I could not hear the audio at all!</p>
<p>A search of the Apple Support forum quickly determined that I was not the only one having this problem.  For example, see <a href="http://discussions.apple.com/thread.jspa?threadID=1888183&amp;tstart=0" target="_blank">http://discussions.apple.com/thread.jspa?threadID=1888183&amp;tstart=0</a> and <a href="http://discussions.apple.com/thread.jspa?threadID=1896387&amp;tstart=0" target="_blank">http://discussions.apple.com/thread.jspa?threadID=1896387&amp;tstart=0</a></p>
<p>Apparently, if you set the speed to other than the Apple Defaults (e.g., 50%, 25%, 12.5%), sometimes the audio volume adjustment is not respected in export, although it works fine when previewed in iMovie.  And sometimes later clips AFTER A TRANSITION do not have their audio if there is an earlier clip somewhere in the movie with one of these non-standard speed adjustments EVEN IF THE AFFECTED CLIP ITSELF DOES NOT HAVE ANY SPEED ADJUSTMENT.  And this occurs on export EVEN IF THE MOVIE PREVIEWS CORRECTLY IN iMOVIE!</p>
<p>This problem appears to occur in all exports, to QuickTime and not to QuickTime, at all speeds, and even to DVD (although I did not test that).</p>
<p>In my case, I was able to workaround the problem by changing the speed of the clip whose audio was still audible to the standard 12.5% (it had the problem when set to 19%), and by deleting two transitions.</p>
<p>Any ideas on how to get Apple to fix its broken iMovie &#8216;09?</p>
]]></content:encoded>
			<wfw:commentRss>http://nachbar.name/blog/2009/02/08/imovie-09-error-audio-exporting-problem/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Konica Minolta Twain Driver Not Recognized</title>
		<link>http://nachbar.name/blog/2008/12/30/konica-minolta-twain-driver-not-recognized/</link>
		<comments>http://nachbar.name/blog/2008/12/30/konica-minolta-twain-driver-not-recognized/#comments</comments>
		<pubDate>Wed, 31 Dec 2008 04:02:17 +0000</pubDate>
		<dc:creator>nachbar</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Atalasoft]]></category>
		<category><![CDATA[Crystal Reports]]></category>
		<category><![CDATA[Konica Minolta]]></category>
		<category><![CDATA[Twain]]></category>

		<guid isPermaLink="false">http://nachbar.name/blog/?p=31</guid>
		<description><![CDATA[I recently had a problem getting the Konica Minolta Twain Driver for the C253 scanner (among others) to be recognized by the twain device manager, and thus it was not listed as one of the twain devices available, either in PhotoShop or in Atalasoft DotTwain.  The nice people at our local Hughes Calihan Konica Minolta [...]]]></description>
			<content:encoded><![CDATA[<p>I recently had a problem getting the Konica Minolta Twain Driver for the C253 scanner (among others) to be recognized by the twain device manager, and thus it was not listed as one of the twain devices available, either in PhotoShop or in <strong>Atalasoft DotTwain</strong>.  The nice people at our local Hughes Calihan Konica Minolta here in Phoenix helped me figure this out, along with Lou Franco of <strong>Atalasoft</strong> (see his comments below), and I wanted to post the solution for anyone having a similar problem.</p>
<p>Ultimately, the problem was that another software package (I believe it was Business Object&#8217;s Crystal Reports XI Release 2), installed a copy of the LIBEAY32.dll into the C:\Windows\System32 directory.  LIBEAY32.dll is part of the open source OpenSSL suite, and I have 18 (!) different versions on my system.  They mostly live in harmony, but when the Konica Minolta twain driver tried to load, it would get the version of LIBEAY32.dll that Crystal Reports had put into System32 (since that is very early in the Dynamic Link Library Search Order &#8212; see <a href="http://msdn.microsoft.com/en-us/library/ms682586.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/ms682586.aspx</a>) and when the LIBEAY32.dll that was loaded did not have the proper ordinal entry point, the Konica Minolta twain driver would not be loaded by the twain device manager.</p>
<p>When PhotoShop loaded, it would emit an error message about the missing ordinal in LIBEAY32.dll; when File/Import was pulled up in the menu, the Konica Minolta twain device would just be missing, and there would be no error here.</p>
<p>Compounding the problem was that my test application using the Twain source manager via the <strong>Atalasoft DotTwain</strong> ShowSelectSource() function did NOT issue any error.</p>
<p>However, a test application I made with Visual C++ loading the Twain device source library for the Konica Minolta scanner did produce the error.</p>
<p>It turns out that the only difference between my test application and Photoshop was the SetErrorMode() function, which sets the process&#8217; ErrorMode.  You can call GetErrorMode() and SetErrorMode() following these imports:<br />
<code>[DllImport("Kernel32.dll")]<br />
private extern static uint SetErrorMode(uint mode);</code></p>
<p><code> </code></p>
<p><code>[DllImport("Kernel32.dll")]<br />
private extern static uint GetErrorMode();</code></p>
<p>If you then call SetErrorMode(0) before the <strong>Atalasoft</strong> ShowSelectSource() function, the user DOES see the error messages from the operating system.  However, the Twain Source Manager twain_32.dll does not return any error code to ShowSelectSource(), so obviously ShowSelectSource() cannot return any error code either.  As noted below, the only way for a calling program to get an indication that a source did not load is to call the twain source DLL directly rather than through the Twain Source Manager, and observe that the LoadLibrary call returns NULL.</p>
<p>Having figured out that the problem was that the Business Objects LIBEAY32.dll was in the System32 directory, the solution was a little difficult.  The Konica Minolta Twain Driver worked once the LIBEAY32.dll was removed  (or renamed) in System32, but Crystal Reports XI Release 2 tries to repair it&#8217;s installation if if finds that file missing. </p>
<p>However, by placing the LIBEAY32.dll from the Konica Minota twain driver directory (in a subdirectory of C:\windows\twain_32, where the twain device files live) into System32, both the Konica Minota twain driver and Crystal Reports seem to be happy.  For good measure, I put a copy of the LIBEAY32.dll that Crystal had put into System32 into Crystal&#8217;s own directory (since that has higher priority in the .dll search order) so that Crystal should load its own LIBEAY32.dll</p>
<p>For reference, I tracked down the problem by making a test Visual Studio C++ app and trying to load the Konica Minolta twain device driver (mostly from <a href="http://msdn.microsoft.com/en-us/library/784bt7z7.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/784bt7z7.aspx</a>) :</p>
<p><code>#include &lt;windows.h&gt;</code></p>
<p>Then, in the click handler:</p>
<p><code>HINSTANCE hDLL; // Handle to DLL<br />
UINT uErrorMode = SetErrorMode(0); // so you get an error message from the OS<br />
LPCWSTR str=L"C:\\Windows\\twain_32\\KONICA MINOLTA\\RTM_V3\\kmtw3R.ds";<br />
hDLL = LoadLibrary(str);</code></p>
<p>The LoadLibrary call produces a MessageBox (see the SetErorrMode() docs) with the error, and returns NULL, if there is a problem loading the twain source driver library. Note that the twain device driver will need other files in that directory, and you will get those errors first; you can fix that problem by adding it to the PATH for testing. The System32 will still be ahead of the PATH (but not ahead of the application .exe directory) so you will get the error message you are looking for. Also note that the twain device driver library, in actual use, will NOT need the PATH to be set; the twain device manager appears to take care of that.  </p>
<p>Another approach that works is to change the current working directory to the directory containing the twain source driver before calling LoadLibrary on the driver, as this will more closely approximate the DLL Search Order used by the twain source manager.  Again, the problem is that, although the source driver does install the files it needs into its own directory, the LIBEAY32.dll that Crystal installs into System32 is still AHEAD of the LIBEAY32.dll installed into the source driver&#8217;s directory!  (see Lou Franco&#8217;s comments below)  DLL Search Order is a fairly complex topic, and can vary depending on a number of factors; google &#8220;Dynamic Link Library Search Order&#8221; for info.  Note that, unless SafeDllSearchMode is disabled, changing the current working directory does not change the DLL search order.</p>
<p>Also, when I tried this with a 64 bit version of Vista, Crystal installs LIBEAY32.dll into /Windows/SysWOW64, which is the directory that takes the place of /Windows/System32.</p>
<p>Regretably, when LoadLibrary fails, FormatMessage produces only a message that the operating system could not run the file.  The only detailed info available seems to be the message box provided directly to the user by the OS, and only when SetErrorMode(0) is in effect.</p>
<p>See also: <a href="http://www.cube316.net/blog/archives/200710/147.html" target="_blank">http://www.cube316.net/blog/archives/200710/147.html</a> for a similar problem.</p>
<p>&#8211; Edited 12/31/08 10PM to add info about using SetErrorMode() to show the error message box, that the lack of error reporting to the application occurs at the Twain Source Manager level, to reinforce the info about DLL Search Order, and to take Lou Franco&#8217;s comments into account; Edited 12/3/09 to add info re 64 bit Vista &#8211;  JMN</p>
]]></content:encoded>
			<wfw:commentRss>http://nachbar.name/blog/2008/12/30/konica-minolta-twain-driver-not-recognized/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
