Hi,

On Fri, 1 Feb 2008, Kirill wrote:

> <not part of the commit message>
> The minimal regedit engine is so big that it's tempting to move it
> from dll.c to a separate module
> </not part of the commit message>

That's a possible next commit, no?  Or if you feel strongly, you can 
introduce registry.[ch], right?

> msysGit (for PathToMsys) is searched in the following order:
> - %PATH%
> - $(TARGET)/..
> - $(TARGET)/../..
> - InstallLocation of uninstall info (machine first, then user).

May I suggest $(TARGET)/.. and $(TARGET)/../.. to be the first two, then 
%PATH%, and then maybe InstallLocation?

> TODO: verify that the found git.exe is really Git

With git-cheetah being installed along the rest of Git (in a hopefully not 
too distant future), this is a non-issue.

> TODO: search for InstallLocation according to the type of the current
>       installation (default or -i:machine)

See above.

> diff --git a/dll.c b/dll.c
> index bab9d9a..40f52ae 100644
> --- a/dll.c
> +++ b/dll.c
> @@ -1,12 +1,129 @@
>  #include <shlobj.h>
> +#include <stdio.h>
>  #include "dll.h"
>  #include "ext.h"
>  #include "factory.h"
> +#include "systeminfo.h"
> 
>  /*
>   * The following is just the necessary infrastructure for having a .dll
>   * which can be registered as a COM object.
>   */
> +static HINSTANCE hInst;
> +
> +static const char *get_module_filename() {
> +     static char module_filename[MAX_PATH] = { '\0' };

AFAIK static variables are initialised all-zero anyway.

> +     if ('\0' == module_filename[0]) {

We tend to write "if (!*module_filename)" for this in git.git.

> +             DWORD module_size;
> +
> +             module_size = GetModuleFileName(hInst, module_filename, 
> MAX_PATH);

This line (and others in your patch) are longer than 80 characters.  
Please cut them, unless there is a compelling reason not to.


> +/* as per "How to: Convert Between System::Guid and _GUID" */
> +static const char *get_class_id()
> +{
> +     static char class_id[MAX_REGISTRY_PATH] = { '\0' };
> +
> +     if ('\0' == class_id[0]) {
> +             GUID guid = CLSID_git_shell_ext;
> +             sprintf (class_id,
> +                     "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
> +                     guid.Data1, guid.Data2, guid.Data3,
> +                     guid.Data4[0], guid.Data4[1], guid.Data4[2], 
> guid.Data4[3],
> +                     guid.Data4[4], guid.Data4[5], guid.Data4[6], 
> guid.Data4[7]);

Again, too long lines.  Besides, could you skip the space after "sprintf"?  
We only have spaces after operators, such as "for", "if", "switch".  
Regular functions do not get a space after the name.

> +static char msysgit[MAX_PATH] = { '\0' };

Again, static variables do not need to be initialised.

> +     if (0 == dwFound ||     // git.exe is not in the PATH or

Please avod C++-style comments (even if we are definitely married to 
gcc/MSVC, which seem to be fine, both, I'd like to keep to the coding 
guidelines of git.git, i.e. /* ... */ instead of // ...).

> +     *(file - 5) = '\0'; // git exe is in "\bin\" from what we really need

You need to make sure that

- file > msysgit + 5, and
- !strncmp(file - 5, "\\bin\\", 5)

and then I'd write this as

        file[-5] = '\0';

> +static const char *find_msysgit()
> +{
> +     if ('\0' == msysgit[0]) {
> +             if (find_msysgit_in_path())
> +                     return msysgit;
> +
> +             // try .. from our own directory

I think that comments like this one are not necessary, as the code is 
self-explanatory:

> +             if (find_msysgit_relative(".."))
> +                     return msysgit;
>
> [...]
>
> +             /* TODO: find an elegant way to pass the installation type
> +                      down here */

Why not a global variable?

> +             if (! find_msysgit_uninstall(HKEY_LOCAL_MACHINE))

Please lose the space after the exclamation mark.

> +/* replaces a substring pattern with a string replacement within a string
> +   the replacement occurs in-place, hence string must be large enough to
> +   hold the result
> +
> +   the function does not handle recursive replacements, e.g.
> +     strreplace ("foo", "bar", "another bar"); // unexpected results
> +
> +   always returns *string
> +*/
> +static char *strreplace(char *string,
> +                                             const char *pattern,
> +                                             const char *replacement)
> +{
> +     char *tail;
> +     char *found = strstr(string, pattern);
> +
> +     while (found) {
> +             tail = strdup(found + strlen(pattern));
> +
> +             *found = '\0';
> +             strcat(string, replacement);
> +             strcat(string, tail);
> +
> +             free(tail);
> +
> +             found = strstr(string, pattern);
> +     }

This is not safe: it does not check the size of "string" anywhere.  I'd 
just pass it in as "size_t size", have "size_t len = strlen(string), 
pattern_len = strlen(pattern), replacement_len = strlen(replacemen_len)".

Then I'd check in the "while (found)" loop if "len + replacement_len - 
pattern_len >= size" (because of the NUL termination, it has to include 
"="), and if that still holds true,

        if (pattern_len != replacement_len)
                memmove(string + found + replacement_len - pattern_len,
                        string + found, len - found - pattern_len + 1);
        memcpy(string + found, replacement, replacement_len);

> +static const REG_VALUE registry_info[] = {
> +     { "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell
> Extensions\\Approved", "@@CLSID@@", "@@PROGRAM_NAME@@" },

How about

#define SHELLEXT "SOFTWARE\\...\\Shell Extensions"

static const REG_VALUE registry_info[] = {
        { SHELLEXT "\\Approved", "@@CLSID@@", "@@PROGRAM_NAME@@" },

?

Also, please use a lower-case name for reg_value (upper-case in the C 
world is commonly used for #define'd stuff).

> +/* supports @@PROGRAM_NAME@@, @@PROGRAM_PATH@@, @@CLSID@@ patterns */
> +static char *get_registry_path(const char *src, char dst[MAX_REGISTRY_PATH])
> +{

Since this function is not called in multi-threaded manner, why not just 
having a "static char dst[MAX_PATH]"?

> +HRESULT PASCAL DllInstall(BOOL bInstall, LPCWSTR pszCmdLine)
>  {
> -     if (reason == DLL_PROCESS_ATTACH) {
> -             object_count = lock_count = 0;
> -             DisableThreadLibraryCalls(instance);
> +     BOOL bMachine = NULL != wcsstr(pszCmdLine, L"machine");

That is not enough, right?  But I agree, we can make that more fool-proof 
later (just imagine somebody happens to call "regsrv32 
C:/machine/git-cheetah.dll").

> +             } else if (bDebug) {
> +                     result = create_reg_entries(HKEY_CURRENT_USER,
> +                                     debug_info);
> +             }

If there is only one line in the clause, please do not use { .. }.

Overall, very nicely done!

Ciao,
Dscho

Reply via email to