C Windowsprogrammierung: Ärgernis oder Fluch?

asdfman

Commander
Registriert
März 2008
Beiträge
2.315
Hab grad ein bisschen mit der win32 API rumprobiert.

- Speicher allozieren mit 3 Parametern? Was ist an malloc() so schlimm?
- Beim Freigeben das selbe.
- APIs mit höhepunkten des Sinngehalts wie "ulOptions - Reserved; must be zero."
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, i, 0, buf, size, NULL);
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL

Wie ist eure Meinung?

Code:
/*
    getkey -- Retrieves Windows XP product keys

    Copyright (c) 2009  asdfmann

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <windows.h>
#include <winreg.h>

#define CRYPTLEN    15
#define KEYLEN      29
#define KEYOFFSET   52

typedef unsigned char uchar;

char *str = "BCDFGHJKMPQRTVWXY2346789";

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
    HKEY CurrentVersion;
    DWORD type = REG_BINARY;
    uchar *key, *buf;
    int ret = EXIT_FAILURE, size = 256, i, j, k, l;
    
    if(((NULL == (buf = (uchar*)HeapAlloc(GetProcessHeap(), 0, size))) || (NULL == (key = (uchar*)HeapAlloc(GetProcessHeap(), 0, KEYLEN + 1)))) && (buf = "HeapAlloc()"))
        goto _error_malloc;

    if(ERROR_SUCCESS != (i = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\0", 0, KEY_READ, &CurrentVersion)))
        goto _error_RegOpen;

    if((ERROR_SUCCESS != (i = RegQueryValueEx(CurrentVersion, "DigitalProductId\0", NULL, &type, buf, &size))) | RegCloseKey(CurrentVersion))
        goto _error_RegOpen;

    for (i = KEYLEN - 1; i > -1; i--) {
        if((i + 1) % 6 == 0)
            key[i] = '-';
        else {
            k = 0;

            for (j = CRYPTLEN; j > -1; j--) {
                l = (k << 8) | buf[j + KEYOFFSET];
                buf[j + KEYOFFSET] = l / 24;
                k = (l % 24);
            }
            
            key[i] = str[k];
        }
    }
    key[KEYLEN] = '\0';
    MessageBox(NULL, key, "Key:", MB_OKCANCEL);
    
    ret = EXIT_SUCCESS;
    goto _free;
    
    _error_RegOpen:
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, i, 0, buf, size, NULL);
    _error_malloc:
        MessageBox(NULL, buf, "Error", MB_OK);
    _free:
        HeapFree(GetProcessHeap(), 0, buf);
        HeapFree(GetProcessHeap(), 0, key);
        return ret;    
}

€:
Ach ja ich hab hier nur XP, ka ob Vista seinen Key anders versteckt, also nicht
wundern, falls das einer kompiliert und eine Fehlermeldung kommt.
 
Zuletzt bearbeitet:
also in vista steht an der selben stelle die digitalproduktid ... ob allerdings deine zweite schleife auch funzt, hab ich einfach mal nicht getestet :D

zur frage malloc: http://en.wikipedia.org/wiki/Malloc#Common_errors

aber was hat das mit windowsprogrammierung zu tun? das ist einfach C ...
windows hat halt noch ein paar eigenarten, aber die kann man mit kleinen subroutinen/libs etc. umgehen.

was ich sagen will, ist, solche speziellen windows-codefragmente sind eine ausnahme für standartbenutzer. (also ist die frage nach fluch oder ärgernis überflüssig)
 
Wie würde das denn in .NET aussehen?
 
[C#]
Code:
using System;
using System.Collections;
using Microsoft.Win32;

class Program
{
    static void Main(string[] args)
    {
        RegistryKey rKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
        byte[] buf = (byte[])rKey.GetValue("DigitalProductId");
        
        const int keyStartIndex = 52;
        const int keyEndIndex = keyStartIndex + 15;
        const int decodeLength = 29;
        const int decodeStringLength = 15;

        char[] digits = new char[]
        {
            'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'M', 'P', 'Q', 'R', 
            'T', 'V', 'W', 'X', 'Y', '2', '3', '4', '6', '7', '8', '9',
        };
        
        char[] decoded = new char[decodeLength];

        ArrayList hexPid = new ArrayList();
        for (int i = keyStartIndex; i <= keyEndIndex; i++)
            hexPid.Add(buf[i]);

        for (int i = decodeLength - 1; i >= 0; i--)
        {
            if ((i + 1) % 6 == 0)
                decoded[i] = '-';
            else
            {
                int dIndex = 0;
                for (int j = decodeStringLength - 1; j >= 0; j--)
                {
                    int byteValue = (dIndex << 8) | (byte)hexPid[j];
                    hexPid[j] = (byte)(byteValue / 24);
                    dIndex = byteValue % 24;
                    decoded[i] = digits[dIndex];
                }
            }
        }

        Console.WriteLine(decoded);
        Console.ReadLine();
    }
}
Ich habe keine Ahnung wie der Key genau "verschlüsselt" ist und deshalb Teile aus dem Internet benutzt. Also "schöner" ist der code definitiv ;)
Fehler hab ich jetzt keine abgefangen, das wäre dann noch zu erledigen, aber da sollte es normalerweise keine Probleme geben, da ja jedes Windows den Key in der Form haben sollte.
Bei mir geht's übrigens auch mit Vista.
 
Zuletzt bearbeitet:
Also der Zugriff auf die Registry sieht definitiv irgendwie sinnvoller gelöst aus.
Hast du vergessen, den Key zu schließen oder macht das der garbage collector?
 
Zurück
Oben