⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 startup.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (C) 2002 Andreas Mohr
 * Copyright (C) 2002 Shachar Shemesh
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/* Based on the Wine "bootup" handler application
 *
 * This app handles the various "hooks" windows allows for applications to perform
 * as part of the bootstrap process. Theses are roughly devided into three types.
 * Knowledge base articles that explain this are 137367, 179365, 232487 and 232509.
 * Also, 119941 has some info on grpconv.exe
 * The operations performed are (by order of execution):
 *
 * Preboot (prior to fully loading the Windows kernel):
 * - wininit.exe (rename operations left in wininit.ini - Win 9x only)
 * - PendingRenameOperations (rename operations left in the registry - Win NT+ only)
 *
 * Startup (before the user logs in)
 * - Services (NT, ?semi-synchronous?, not implemented yet)
 * - HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServicesOnce (9x, asynch)
 * - HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServices (9x, asynch)
 *
 * After log in
 * - HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce (all, synch)
 * - HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run (all, asynch)
 * - HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run (all, asynch)
 * - Startup folders (all, ?asynch?, no imp)
 * - HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce (all, asynch)
 *
 * Somewhere in there is processing the RunOnceEx entries (also no imp)
 *
 * Bugs:
 * - If a pending rename registry does not start with \??\ the entry is
 *   processed anyways. I'm not sure that is the Windows behaviour.
 * - Need to check what is the windows behaviour when trying to delete files
 *   and directories that are read-only
 * - In the pending rename registry processing - there are no traces of the files
 *   processed (requires translations from Unicode to Ansi).
 */

#include <stdio.h>
#include <windows.h>
#include <ctype.h>

/**
 * Performs the rename operations dictated in %SystemRoot%\Wininit.ini.
 * Returns FALSE if there was an error, or otherwise if all is ok.
 */
static BOOL wininit()
{
    return TRUE;
}

static BOOL pendingRename()
{
    static const WCHAR ValueName[] = {'P','e','n','d','i','n','g',
                                      'F','i','l','e','R','e','n','a','m','e',
                                      'O','p','e','r','a','t','i','o','n','s',0};
    static const WCHAR SessionW[] = { 'S','y','s','t','e','m','\\',
                                     'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
                                     'C','o','n','t','r','o','l','\\',
                                     'S','e','s','s','i','o','n',' ','M','a','n','a','g','e','r',0};
    WCHAR *buffer=NULL;
    const WCHAR *src=NULL, *dst=NULL;
    DWORD dataLength=0;
    HKEY hSession=NULL;
    DWORD res;

    printf("Entered\n");

    if ((res=RegOpenKeyExW(HKEY_LOCAL_MACHINE, SessionW, 0, KEY_ALL_ACCESS, &hSession))
            !=ERROR_SUCCESS)
    {
        if (res==ERROR_FILE_NOT_FOUND)
        {
            printf("The key was not found - skipping\n");
            res=TRUE;
        }
        else
        {
            printf("Couldn't open key, error %ld\n", res);
            res=FALSE;
        }

        goto end;
    }

    res=RegQueryValueExW(hSession, ValueName, NULL, NULL /* The value type does not really interest us, as it is not
                                                             truely a REG_MULTI_SZ anyways */,
            NULL, &dataLength);
    if (res==ERROR_FILE_NOT_FOUND)
    {
        /* No value - nothing to do. Great! */
        printf("Value not present - nothing to rename\n");
        res=TRUE;
        goto end;
    }

    if (res!=ERROR_SUCCESS)
    {
        printf("Couldn't query value's length (%ld)\n", res);
        res=FALSE;
        goto end;
    }

    buffer=malloc(dataLength);
    if (buffer==NULL)
    {
        printf("Couldn't allocate %lu bytes for the value\n", dataLength);
        res=FALSE;
        goto end;
    }

    res=RegQueryValueExW(hSession, ValueName, NULL, NULL, (LPBYTE)buffer, &dataLength);
    if (res!=ERROR_SUCCESS)
    {
        printf("Couldn't query value after successfully querying before (%lu),\n"
                "please report to wine-devel@winehq.org\n", res);
        res=FALSE;
        goto end;
    }

    /* Make sure that the data is long enough and ends with two NULLs. This
     * simplifies the code later on.
     */
    if (dataLength<2*sizeof(buffer[0]) ||
            buffer[dataLength/sizeof(buffer[0])-1]!='\0' ||
            buffer[dataLength/sizeof(buffer[0])-2]!='\0')
    {
        printf("Improper value format - doesn't end with NULL\n");
        res=FALSE;
        goto end;
    }

    for(src=buffer; (src-buffer)*sizeof(src[0])<dataLength && *src!='\0';
            src=dst+lstrlenW(dst)+1)
    {
        DWORD dwFlags=0;

        printf("processing next command\n");

        dst=src+lstrlenW(src)+1;

        /* We need to skip the \??\ header */
        if (src[0]=='\\' && src[1]=='?' && src[2]=='?' && src[3]=='\\')
            src+=4;

        if (dst[0]=='!')
        {
            dwFlags|=MOVEFILE_REPLACE_EXISTING;
            dst++;
        }

        if (dst[0]=='\\' && dst[1]=='?' && dst[2]=='?' && dst[3]=='\\')
            dst+=4;

        if (*dst!='\0')
        {
            /* Rename the file */
            MoveFileExW(src, dst, dwFlags);
        } else
        {
            /* Delete the file or directory */
			res = GetFileAttributesW (src);
            if (res != (DWORD)-1)
            {
                if ((res&FILE_ATTRIBUTE_DIRECTORY)==0)
                {
                    /* It's a file */
                    DeleteFileW(src);
                } else
                {
                    /* It's a directory */
                    RemoveDirectoryW(src);
                }
            } else
            {
                printf("couldn't get file attributes (%ld)\n", GetLastError());
            }
        }
    }

    if ((res=RegDeleteValueW(hSession, ValueName))!=ERROR_SUCCESS)
    {
        printf("Error deleting the value (%lu)\n", GetLastError());
        res=FALSE;
    } else
        res=TRUE;

end:
    if (buffer!=NULL)
        free(buffer);

    if (hSession!=NULL)
        RegCloseKey(hSession);

    return res;
}

enum runkeys {
    RUNKEY_RUN, RUNKEY_RUNONCE, RUNKEY_RUNSERVICES, RUNKEY_RUNSERVICESONCE
};

const WCHAR runkeys_names[][30]=
{
    {'R','u','n',0},
    {'R','u','n','O','n','c','e',0},
    {'R','u','n','S','e','r','v','i','c','e','s',0},
    {'R','u','n','S','e','r','v','i','c','e','s','O','n','c','e',0}
};

#define INVALID_RUNCMD_RETURN -1
/**
 * This function runs the specified command in the specified dir.
 * [in,out] cmdline - the command line to run. The function may change the passed buffer.
 * [in] dir - the dir to run the command in. If it is NULL, then the current dir is used.
 * [in] wait - whether to wait for the run program to finish before returning.
 * [in] minimized - Whether to ask the program to run minimized.
 *
 * Returns:
 * If running the process failed, returns INVALID_RUNCMD_RETURN. Use GetLastError to get the error code.
 * If wait is FALSE - returns 0 if successful.
 * If wait is TRUE - returns the program's return value.
 */
static int runCmd(LPWSTR cmdline, LPCWSTR dir, BOOL wait, BOOL minimized)
{
    STARTUPINFOW si;
    PROCESS_INFORMATION info;
    DWORD exit_code=0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -