    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Typesafe Registry for Windows</title>
        <link>https://members.accu.org/index.php/journals/457</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>


        <h2>Journal Articles</h2>


<div class="xar-mod-head"><span class="xar-mod-title">Overload Journal #42 - Apr 2001 + Programming Topics</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c162/">42</a>
                    (9)
<br />

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c65/">Programming</a>
                    (877)
<br />

                                            <a href="https://members.accu.org/index.php/journals/c162-65/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/journals/c162+65/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Typesafe Registry for Windows</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 26 April 2001 17:46:06 +01:00 or Thu, 26 April 2001 17:46:06 +01:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e18" id="d0e18"></a></h2>
</div>
<p>The windows API provides generic methods for transferring data
to and from the registry. This generality means that the actual
data needs to be coerced into and out of a byte array. This on it's
own is not enough; the type of the data is also required. The
functions also provide the type of data. When reading data from the
windows registry the following function is used in win32.</p>
<pre class="programlisting">
LONG RegQueryValueEx(
  HKEY hKey,            // handle to key
  LPCTSTR lpValueName,  // value name
  LPDWORD lpReserved,   // reserved
  LPDWORD lpType,       // type buffer
  LPBYTE lpData,        // data buffer
  LPDWORD lpcbData      // size of data buffer
);
</pre>
<p>As you can see the data is returned as a number of bytes, which
means code that uses this function is often written as:</p>
<pre class="programlisting">
int StartParam;
DWORD Type = 0;
DWORD Size = sizeof(StartParam);
RegQueryValueEx(hkey, &quot;Start&quot;, NULL, &amp;Type, (BYTE*)&amp;StartParam, &amp;Size);
</pre>
<p>To properly check that the value has been read correctly the
<tt class="varname">Type</tt> variable would be checked for the
correct type e.g. <tt class="literal">REG_DWORD</tt>. If there was
a mismatch then an error needs to be reported as the data in
<tt class="varname">StartParam</tt> is meaningless. A better
approach would be to wrap the registry API. All the error checking
will now be in a single class and therefore much easier to manage.
In order for this to provide a typesafe interface the designer must
make the class support at least the built-types for the registry.
The class would also have to be designed for derivation so that it
could be extended to support <span class="type">bool</span> for
example.</p>
<p>The registry interface has been wrapped in C++ many times so one
more won't hurt. I like to use STL, so I require that the interface
makes the registry look like an STL container, the following is
required:</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>Read data in a typesafe way.</p>
</li>
<li>
<p>Write data in a typesafe way.</p>
</li>
<li>
<p>Provide a mechanism to iterate values.</p>
</li>
<li>
<p>Provide a mechanism to iterate keys.</p>
</li>
<li>
<p>Errors to be propagated as exceptions.</p>
</li>
<li>
<p>Provide a simple and concise interface.</p>
</li>
<li>
<p>Encapsulate all in a namespace</p>
</li>
</ul>
</div>
<p>Initially I set about writing a simple program to open a
registry key and read a <span class="type">DWORD</span> value. I
created a simple class to encapsulate the concept of an
<span class="type">HKEY</span> value:</p>
<pre class="programlisting">
class Key {
public:
  typedef ref_count&lt;Key&gt; RCKey;
  Key(HKEY key): mKey(key) {}
  ~Key() {::RegCloseKey(mKey);}
  HKEY GetHandle() const {return mKey;}
private:
  HKEY mKey;
};
</pre>
<p>Opening a registry key is a stand alone operation so I created
the <tt class="function">Open</tt> function:</p>
<pre class="programlisting">
Key::RCKey Open(HKEY key, LPCTSTR sub_key){
  HKEY temp_key;
  CheckReturn(::RegOpenKeyEx(key, sub_key, 0, KEY_ALL_ACCESS, &amp;temp_key));
  return Key::RCKey(new Key(temp_key));
}
</pre>
<p>The registry key will be closed when the <tt class=
"classname">Key</tt> instance goes out of scope. Why return the key
as reference counted object? I did not want a function using a
registry key to have access errors because the key had been closed
elsewhere in the code. This type of problem could be difficult to
track down.</p>
<p>Now moving on to the more interesting parts.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e90" id="d0e90"></a>Reading and
writing a DWORD to a registry entry</h2>
</div>
<pre class="programlisting">
typedef std::vector&lt;BYTE&gt; Buffer;
DWORD GetValue(LPCTSTR sub_key){
  DWORD length = 0;
  DWORD type;
  try {
    CheckReturn(::RegQueryValueEx(mKey,sub_key, 0, &amp;type, 0, &amp;length));
    Buffer buffer;
    buffer.resize(length);
    CheckReturn(::RegQueryValueEx(mKey, sub_key, 0, &amp;type, &amp;buffer[0],&amp;length));
    return *( reinterpret_cast&lt;DWORD *&gt;(&amp;buffer[0]));
  }
  catch(const Exception&amp; e) {
    std::stringstream s;
    s &lt;&lt; &quot;Registry Error: Accessing '&quot; &lt;&lt; sub_key &lt;&lt; &quot;' &quot; &lt;&lt; e.What();
    throw Exception(s.str().c_str(), e.ErrorCode());
  }
}
</pre>
<p>The <tt class="function">CheckReturn</tt> function tests the
return code and will throw an exception if it is not <tt class=
"literal">ERROR_SUCCESS</tt>. Why catch the exception within the
function, why not just let it propagate through. If you use the
Win32 <tt class="function">FormatMessage</tt> function with a
registry error you will see just generic text like 'File not
found'. This is clearly inadequate when the class can report extra
information to the client.</p>
<p>Because of the non-typesafe interface to the registry reading a
string requires the same sequence of operations, but casting to a
string as the end result. A function would be written for each
return type that needs to be retrieved from the registry. Alas a
problem looms, the return type is not part of the function
signature. So by having two functions:</p>
<pre class="programlisting">
DWORD GetValue(LPCTSTR sub_key);
std::string GetValue(LPCTSTR sub_key);
</pre>
<p>The compiler will generate errors with the functions only
differing by return type.</p>
<p>Hmmmm ...</p>
<p>With a slight modification the functions now look like:</p>
<pre class="programlisting">
void GetValue(LPCTSTR sub_key, DWORD&amp; dw);
void GetValue(LPCTSTR sub_key, std::string&amp; str);
</pre>
<p>Now there are no errors, but we have to write a function for
each type we need to support. That could be a lot of typing, plus
the functions are almost the same.</p>
<p>(enter stage left: Sir template with the sword of hope)</p>
<p>By exploiting the use of traits and template functions, a
generic typesafe interface can be created.</p>
<div class="variablelist">
<dl>
<dt><span class="term">Commonality</span></dt>
<dd>
<p>The method of retrieving the data from the registry is the same
regardless of the data type.</p>
</dd>
<dt><span class="term">Variability</span></dt>
<dd>
<p>The method of converting the data is dependent upon the type
required.</p>
</dd>
</dl>
</div>
<p>By using a <tt class="classname">ConvertTraits</tt> class the
variability can be specified by the type of data required. This
involves creating a null implementation for the general case and
specific ones for the data types required. The null case will then
cause the compiler to emit errors for unsupported types.</p>
<pre class="programlisting">
template &lt;typename _t&gt; struct ConvertTraits;
template&lt;&gt;
struct ConvertTraits&lt;DWORD&gt; {
  enum { reg_type = REG_DWORD };
  static LPCTSTR exceptionMessage(){ return &quot;REG_DWORD: Can't convert to DWORD&quot;;
}
  static void Read(DWORD&amp; dw, DWORD type,Buffer&amp; buffer){
    dw = *(reinterpret_cast&lt;DWORD *&gt;(&amp;buffer[0]));
  }
//...
};
template&lt;&gt;
struct ConvertTraits&lt;std::string&gt;{
  enum { reg_type = REG_SZ };
  static LPCTSTR exceptionMessage(){ return &quot;REG_SZ: Can't convert to string&quot;;
}
  static void Read(std::string&amp; str, DWORD type, Buffer&amp; buffer){
  str = std::string(reinterpret_cast&lt;TCHAR *&gt;(&amp;buffer[0]));
  }
//...
};
</pre>
<p>The template function to retrieve the data from the registry
uses the traits class to perform the specific conversions
required.</p>
<pre class="programlisting">
template&lt;typename _t&gt;
void GetValue(LPCTSTR sub_key, _t&amp; val){
  typedef ConvertTraits&lt;_t&gt; traits;
  DWORD length = 0;
  DWORD type = 0;
  try {
    CheckReturn(::RegQueryValueEx(mKey, sub_key, 0, &amp;type, 0, &amp;length));
    Buffer buffer;
    buffer.resize(length);
    CheckReturn(::RegQueryValueEx(mKey, sub_key, 0, &amp;type, &amp;buffer[0], &amp;length));
    if(traits::reg_type == type)
    traits::Read(val, type, buffer);
  else
    throw Exception(traits::exceptionMessage(), 0);
  }
  catch(const Exception&amp; e){
    std::stringstream s;
    s &lt;&lt; &quot;Registry Error: Accessing '&quot; &lt;&lt; sub_key &lt;&lt; &quot;' &quot; &lt;&lt; e.What();
    throw Exception(s.str().c_str(), e.ErrorCode());
  }
}
</pre>
<p>With this function part of the Key class we can now write
convenient typesafe routines:</p>
<pre class="programlisting">
void Test(){
  try {
    registry::Key::RCKey key = registry::Open(HKEY_LOCAL_MACHINE, &quot;SOFTWARE\\Test&quot;);
// read value
    DWORD dw;
    key-&gt;GetValue(&quot;DwordTest&quot;, dw);
    // some string stuff
    std::string str;
    key-&gt;GetValue(&quot;StringTest&quot;, str);
  }
  catch(const registry::Exception&amp; e){
    std::stringstream s;
    s &lt;&lt; e.What() &lt;&lt; &quot; &quot; &lt;&lt; std::hex &lt;&lt; e.ErrorCode();
    ::OutputDebugString(s.str().c_str());
    ::OutputDebugString(&quot;\n&quot;);
  }
}
</pre>
<p>Writing values back to the registry is easier than reading them,
but with one twist. The type of the data is required. This is the
type to map to in the registry, <span class="type">DWORD</span> to
<span class="type">REG_DEWORD</span> and <tt class=
"classname">std::string</tt> to <span class="type">REGS_SZ</span>.
In the <tt class="classname">ConvertTraits</tt> class an <tt class=
"literal">enum</tt> <span class="type">reg_type</span> is defined,
this is the type used by the registry. The write function of the
traits class is simple, convert the user type to a <span class=
"type">byte</span> array, for <span class="type">DWORD</span> it
could be:</p>
<pre class="programlisting">
template&lt;&gt;
struct ConvertTraits&lt;DWORD&gt;{
//...
  static void Write(DWORD&amp; dw, Buffer&amp; buffer) {
    buffer.resize(sizeof(DWORD));
    ::memcpy(&amp;buffer[0], &amp;dw, sizeof(DWORD));
  }
};
</pre>
<p>and a string:</p>
<pre class="programlisting">
template&lt;&gt;
struct ConvertTraits&lt;std::string&gt; {
//...
  static void Write(std::string&amp; str, Buffer&amp; buffer) {
    buffer.resize(str.length());
    std::copy(str.begin(), str.end(), buffer.begin());
  }
};
</pre>
<p>Then the <tt class="function">SetValue</tt> template function
can be written using the traits <span class="type">reg_type</span>
to define the type used by the registry.</p>
<pre class="programlisting">
template&lt;typename _t&gt; 
void SetValue(LPCTSTR sub_key, _t&amp; val){
  typedef ConvertTraits&lt;_t&gt; traits;
  try   {
    Buffer buffer;
    traits::Write(val, buffer);
    CheckReturn(::RegSetValueEx(mKey, sub_key, 0, traits::reg_type, 
                          &amp;buffer[0], buffer.size()));
  }
  catch(const Exception&amp; e) {
    std::stringstream s;
    s &lt;&lt; &quot;Registry Error: Writing '&quot; &lt;&lt; sub_key &lt;&lt; &quot;' &quot; &lt;&lt; e.What();
    throw Exception(s.str().c_str(), e.ErrorCode());
  }
}
</pre>
<p>The final part is to generate two iterators to allow traversal
of the sub-keys and values for the key object. The sub-key iterator
returns the name of the key. The value iterator returns a structure
containing both the name and the type of the entry. The registry
class can then be used in any place where a forward iterator is
valid.</p>
<pre class="programlisting">
registry::Key::value_iterator value_it = key-&gt;ValueBegin();
while(value_it != key-&gt;ValueEnd()){
  registry::Key::value_iterator::value_type data = (*value_it);
  ++value_it;
}
registry::Key::key_iterator key_it = key-&gt;KeyBegin();
while(key_it != key-&gt;KeyEnd()){
  std::string key_txt = (*key_it);
  ++key_it;
}
</pre>
<p>The registry key class is open for extension, to add a new type
all a user of the class is required to do is provide a suitable
<tt class="classname">ConvertTraits</tt> class and leave the rest
to the existing code.</p>
<p>This article and source code as a VC6 project is available by
sending an email to <tt class="email">&lt;<a href=
"mailto:samples@componentx.co.uk">samples@componentx.co.uk</a>&gt;</tt>
with the subject line of registry.</p>
</div>
<div class="bibliography">
<div class="titlepage">
<h2><a name="d0e211" id="d0e211"></a>References</h2>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="citetitle"><i class=
"citetitle">C++ Programming Language</i></span> (Stroustrup)</p>
</div>
<div class="bibliomixed">
<p class="bibliomixed">MSDN (Microsoft)</p>
</div>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
