Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

842 lines
16 KiB

/*++
Copyright (c) 2002 Microsoft Corporation
Module Name:
srcsrv.cpp
Abstract:
This code obtaining version-controlled source.
Author:
patst
--*/
#include "pch.h"
BOOL gInitialized = false;
LIST_ENTRY gProcessList;
DWORD gProcessListCount = 0;
DWORD gOptions = 0;
BOOL
DllMain(
IN PVOID hdll,
IN ULONG reason,
IN PCONTEXT context OPTIONAL
)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return true;
}
BOOL error(DWORD err)
{
SetLastError(err);
return false;
}
PVOID MemAlloc(DWORD size)
{
PVOID rc;
rc = LocalAlloc(LPTR, size);
if (!rc)
return rc;
ZeroMemory(rc, size);
return rc;
}
void MemFree(PVOID p)
{
if (p)
LocalFree(p);
}
PPROCESS_ENTRY FindProcessEntry(HANDLE hp)
{
PLIST_ENTRY next;
PPROCESS_ENTRY pe;
DWORD count;
next = gProcessList.Flink;
if (!next)
return NULL;
for (count = 0; (PVOID)next != (PVOID)&gProcessList; count++)
{
assert(count < gProcessListCount);
if (count >= gProcessListCount)
return NULL;
pe = CONTAINING_RECORD(next, PROCESS_ENTRY, ListEntry);
next = pe->ListEntry.Flink;
if (pe->hProcess == hp)
return pe;
}
return NULL;
}
PPROCESS_ENTRY
FindFirstProcessEntry(
)
{
return CONTAINING_RECORD(gProcessList.Flink, PROCESS_ENTRY, ListEntry);
}
void
SendDebugString(
PPROCESS_ENTRY pe,
LPSTR sz
)
{
__try
{
if (!pe)
pe = FindFirstProcessEntry();
if (!pe || !pe->callback)
return;
pe->callback(SRCSRVACTION_TRACE, (DWORD64)sz, pe->context);
} __except (EXCEPTION_EXECUTE_HANDLER) {
}
}
#define dprint ((gOptions & SRCSRVOPT_DEBUG) == SRCSRVOPT_DEBUG)&&_dprint
#define eprint ((gOptions & SRCSRVOPT_DEBUG) == SRCSRVOPT_DEBUG)&&_eprint
#define pdprint ((gOptions & SRCSRVOPT_DEBUG) == SRCSRVOPT_DEBUG)&&_pdprint
#define pdeprint ((gOptions & SRCSRVOPT_DEBUG) == SRCSRVOPT_DEBUG)&&_pdeprint
bool
_pdprint(
PPROCESS_ENTRY pe,
LPSTR format,
...
)
{
static char buf[1000] = "SRCSRV: ";
va_list args;
va_start(args, format);
_vsnprintf(buf+9, sizeof(buf)-9, format, args);
va_end(args);
SendDebugString(pe, buf);
return true;
}
bool
_peprint(
PPROCESS_ENTRY pe,
LPSTR format,
...
)
{
static char buf[1000] = "";
va_list args;
va_start(args, format);
_vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
SendDebugString(pe, buf);
return true;
}
bool
_dprint(
LPSTR format,
...
)
{
static char buf[1000] = "SRCSRV: ";
va_list args;
va_start(args, format);
_vsnprintf(buf+9, sizeof(buf)-9, format, args);
va_end(args);
SendDebugString(NULL, buf);
return true;
}
bool
_eprint(
LPSTR format,
...
)
{
static char buf[1000] = "";
va_list args;
va_start(args, format);
_vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
SendDebugString(NULL, buf);
return true;
}
void FreeModuleEntry(PPROCESS_ENTRY pe, PMODULE_ENTRY me)
{
MemFree(me->stream);
MemFree(me);
}
PMODULE_ENTRY
FindModuleEntry(
PPROCESS_ENTRY pe,
DWORD64 base
)
{
static PLIST_ENTRY next = NULL;
PMODULE_ENTRY me;
if (base == (DWORD64)-1)
{
if (!next)
return NULL;
if ((PVOID)next == (PVOID)&pe->ModuleList)
{
// Reset to NULL so the list can be re-walked
next = NULL;
return NULL;
}
me = CONTAINING_RECORD( next, MODULE_ENTRY, ListEntry );
next = me->ListEntry.Flink;
return me;
}
next = pe->ModuleList.Flink;
if (!next)
return NULL;
while ((PVOID)next != (PVOID)&pe->ModuleList)
{
me = CONTAINING_RECORD(next, MODULE_ENTRY, ListEntry);
next = me->ListEntry.Flink;
if (base == me->base)
return me;
}
return NULL;
}
char *
dotranslate(
PMODULE_ENTRY me,
char *input,
char *output,
DWORD outsize
)
{
int i;
char key[MAX_PATH + 1];
PVARIABLE var;
int cbkey;
char *s;
char *p;
assert(me && input && *input && output);
*output = 0;
for (i = 0, var = me->vars; i < me->cvars; i++, var++)
{
CopyStrArray(key, "${");
CatStrArray(key, var->key);
CatStrArray(key, "}");
cbkey = strlen(var->key) + 3;
for (s = input, p = strstr(s, key); p; s = p + cbkey, p = strstr(s, key))
{
CatNString(output, s, p - s, outsize);
CatString(output, var->val, outsize);
}
}
if (!*output)
CopyString(output, input, outsize);
return output;
}
#define translate(me, input, output) dotranslate(me, input, output, DIMA(output))
PSDFILE
find(
PMODULE_ENTRY me,
const char *file
)
{
int i;
PSDFILE sdf;
for (i = 0, sdf = me->sdfiles; i < me->cfiles; i++, sdf++)
{
if (!_strcmpi(sdf->path, file))
return sdf;
}
return NULL;
}
void
DumpModuleEntries(
PPROCESS_ENTRY pe
)
{
static PLIST_ENTRY next = NULL;
PMODULE_ENTRY me;
PVARIABLE vars;
PSDFILE sdfiles;
char path[MAX_PATH + 1];
char depot[MAX_PATH + 1];
char loc[MAX_PATH + 1];
next = pe->ModuleList.Flink;
if (!next)
return;
while ((PVOID)next != (PVOID)&pe->ModuleList)
{
me = CONTAINING_RECORD(next, MODULE_ENTRY, ListEntry);
dprint("%s 0x%x\n", me->name, me->base);
dprint("variables:\n");
for (vars = me->vars; vars->key; vars++)
dprint("%s=%s\n", vars->key, vars->val);
dprint("source depot files:\n");
for (sdfiles = me->sdfiles; sdfiles->path; sdfiles++)
{
translate(me, sdfiles->path, path);
translate(me, sdfiles->depot, depot);
translate(me, sdfiles->loc, loc);
dprint("%s %s %s\n", path, depot, loc);
}
eprint("\n");
next = me->ListEntry.Flink;
}
}
char *
GetLine(
char *sz
)
{
for (;*sz; sz++)
{
if (*sz == '\n' || *sz == '\r')
{
*sz++ = 0;
if (*sz == 10)
sz++;
return (*sz) ? sz : NULL;
}
}
return NULL;
}
int
SetBlock(
char *sz
)
{
static char *labels[blMax] =
{
"SRCSRV: end", // blNone
"SRCSRV: variables", // blVars
"SRCSRV: source files" // blSource
};
static int lens[blMax] =
{
sizeof("SRCSRV: end") / sizeof(char) -1 , // blNone
sizeof("SRCSRV: variables") / sizeof(char) -1 , // blVars
sizeof("SRCSRV: source files") / sizeof(char) -1 // blSource
};
int i;
char *label;
for (i = blNone; i < blMax; i++)
{
label = labels[i];
if (!strncmp(sz, label, lens[i]))
return i;
}
return blMax;
}
bool
ParseVars(
char *sz,
PVARIABLE var
)
{
char *p;
p = (strchr(sz, '='));
if (!p)
return false;
*p = 0;
var->key = sz;
var->val = p + 1;
return true;
}
bool
ParseSD(
char *sz,
PSDFILE sdfile
)
{
char *p;
char *g;
sz += 4;
p = (strchr(sz, '*'));
if (!p)
return false;
*p++ = 0;
g = (strchr(p, '*'));
if (!g)
return false;
*g++ = 0;
sdfile->path = sz;
sdfile->depot = p;
sdfile->loc = g;
return true;
}
BOOL
IndexStream(
PMODULE_ENTRY me
)
{
char *sz;
char *next;
int block;
int lines;
int bl;
PVARIABLE vars;
PSDFILE sdfiles;
// count the lines
for (sz = me->stream, lines = 0; *sz; sz++)
{
if (*sz == '\n')
lines++;
}
if (!lines)
return false;
me->vars = (PVARIABLE)MemAlloc(lines * sizeof(VARIABLE));
if (!me->vars)
return error(ERROR_NOT_ENOUGH_MEMORY);
me->sdfiles = (PSDFILE)MemAlloc(lines * sizeof(SDFILE));
if (!me->sdfiles)
return error(ERROR_NOT_ENOUGH_MEMORY);
block = blNone;
vars = me->vars;
sdfiles = me->sdfiles;
me->cfiles = 0;
me->cvars = 0;
for (sz = me->stream; sz; sz = next)
{
next = GetLine(sz);
bl = SetBlock(sz);
// dprint("%s\n", sz);
if (bl != blMax)
{
block = bl;
continue;
}
switch(block)
{
case blVars:
if (ParseVars(sz, vars))
{
vars++;
me->cvars++;
}
break;
case blSource:
if (ParseSD(sz, sdfiles))
{
sdfiles++;
me->cfiles++;
}
break;
}
}
#if 0
DumpIndexes(me);
#endif
return true;
}
DWORD
WINAPI
SrcSrvSetOptions(
DWORD opts
)
{
DWORD rc = gOptions;
gOptions = opts;
return rc;
}
DWORD
WINAPI
SrcSrvGetOptions(
)
{
return gOptions;
}
BOOL
WINAPI
SrcSrvInit(
HANDLE hProcess,
LPCSTR path
)
{
PPROCESS_ENTRY pe;
// test the path for copying files to...
if (!path || !*path)
return error(ERROR_INVALID_PARAMETER);
if (!EnsurePathExists(path, NULL, 0, TRUE))
return false;
if (!gInitialized)
{
gInitialized = true;
InitializeListHead(&gProcessList);
}
if (pe = FindProcessEntry(hProcess))
{
pe->cRefs++;
return error(ERROR_INVALID_HANDLE);
}
pe = (PPROCESS_ENTRY)MemAlloc(sizeof(PROCESS_ENTRY));
if (!pe)
return error(ERROR_NOT_ENOUGH_MEMORY);
pe->hProcess = hProcess;
pe->cRefs = 1;
CopyStrArray(pe->path, path);
gProcessListCount++;
InitializeListHead(&pe->ModuleList);
InsertTailList(&gProcessList, &pe->ListEntry);
return true;
}
BOOL
WINAPI
SrcSrvCleanup(
HANDLE hProcess
)
{
PPROCESS_ENTRY pe;
PLIST_ENTRY next;
PMODULE_ENTRY me;
pe = FindProcessEntry(hProcess);
if (!pe)
return error(ERROR_INVALID_HANDLE);
if (--pe->cRefs)
return true;
next = pe->ModuleList.Flink;
if (next)
{
while (next != &pe->ModuleList)
{
me = CONTAINING_RECORD(next, MODULE_ENTRY, ListEntry);
next = me->ListEntry.Flink;
FreeModuleEntry(pe, me);
}
}
RemoveEntryList(&pe->ListEntry);
MemFree(pe);
gProcessListCount--;
return true;
}
BOOL
WINAPI
SrcSrvSetTargetPath(
HANDLE hProcess,
LPCSTR path
)
{
PPROCESS_ENTRY pe;
pe = FindProcessEntry(hProcess);
if (!pe)
return error(ERROR_INVALID_HANDLE);
// test the path for copying files to...
if (!path || !*path)
return error(ERROR_INVALID_PARAMETER);
if (!EnsurePathExists(path, NULL, 0, TRUE))
return false;
// store the new path
CopyStrArray(pe->path, path);
return true;
}
BOOL
WINAPI
SrcSrvLoadModule(
HANDLE hProcess,
LPCSTR name,
DWORD64 base,
PVOID stream,
DWORD size
)
{
PPROCESS_ENTRY pe;
PMODULE_ENTRY me;
if (!base || !name || !*name || !stream || !*(PCHAR)stream || !size)
return error(ERROR_INVALID_PARAMETER);
pe = FindProcessEntry(hProcess);
if (!pe)
return error(ERROR_INVALID_PARAMETER);
me = FindModuleEntry(pe, base);
if (me)
SrcSrvUnloadModule(pe, base);
me = (PMODULE_ENTRY)MemAlloc(sizeof(MODULE_ENTRY));
if (!me)
return error(ERROR_NOT_ENOUGH_MEMORY);
me->base = base;
CopyStrArray(me->name, name);
me->stream = (char *)MemAlloc(size);
if (!me->stream)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto error;
}
memcpy(me->stream, stream, size);
me->cbStream = size;
dprint(me->stream);
IndexStream(me);
InsertTailList(&pe->ModuleList, &me->ListEntry);
DumpModuleEntries(pe);
return true;
error:
FreeModuleEntry(pe, me);
return false;
}
BOOL
WINAPI
SrcSrvUnloadModule(
HANDLE hProcess,
DWORD64 base
)
{
PPROCESS_ENTRY pe;
PLIST_ENTRY next;
PMODULE_ENTRY me;
pe = FindProcessEntry(hProcess);
if (!pe)
return error(ERROR_INVALID_PARAMETER);
next = pe->ModuleList.Flink;
if (!next)
return error(ERROR_MOD_NOT_FOUND);
while (next != &pe->ModuleList)
{
me = CONTAINING_RECORD(next, MODULE_ENTRY, ListEntry);
if (me->base == base)
{
RemoveEntryList(next);
FreeModuleEntry(pe, me);
return true;
}
next = me->ListEntry.Flink;
}
return error(ERROR_MOD_NOT_FOUND);
}
BOOL
WINAPI
SrcSrvRegisterCallback(
HANDLE hProcess,
PSRCSRVCALLBACKPROC callback,
DWORD64 context
)
{
PPROCESS_ENTRY pe;
pe = FindProcessEntry(hProcess);
if (!pe)
return error(ERROR_INVALID_PARAMETER);
pe->callback = callback;
pe->context = context;
return true;
}
BOOL
WINAPI
SrcSrvGetFile(
HANDLE hProcess,
DWORD64 base,
LPCSTR filename,
LPSTR target,
DWORD trgsize
)
{
PPROCESS_ENTRY pe;
PMODULE_ENTRY me;
PSDFILE sdf;
char name[MAX_PATH + 1];
char ext[MAX_PATH + 1];
BOOL rc;
char depot[MAX_PATH + 1];
char loc[MAX_PATH + 1];
char cmd[MAX_PATH * 2];
STARTUPINFO si;
PROCESS_INFORMATION pi;
if (!base || !filename || !*filename || !target)
return error(ERROR_INVALID_PARAMETER);
*target = 0;
pe = FindProcessEntry(hProcess);
if (!pe)
return error(ERROR_INVALID_HANDLE);
me = FindModuleEntry(pe, base);
if (!me)
return error(ERROR_MOD_NOT_FOUND);
// get the matching file entry
sdf = find(me, filename);
if (!sdf)
return error(ERROR_FILE_NOT_FOUND);
// build the target path and command line for source depot
#if 0
_splitpath(filename, NULL, NULL, name, ext);
strcpy(target, pe->path); // SECURITY: Don't know size of target buffer.
EnsureTrailingBackslash(target);
strcat(target, name); // SECURITY: Don't know size of target buffer.
strcat(target, ext); // SECURITY: Don't know size of target buffer.
CreateTargetPath(pe, sdf, target);
#else
strcpy(target, pe->path); // SECURITY: Don't know size of target buffer.
EnsureTrailingBackslash(target);
_splitpath(filename, NULL, NULL, name, ext);
strcat(target, name); // SECURITY: Don't know size of target buffer.
if (*ext)
strcat(target, ext); // SECURITY: Don't know size of target buffer.
#endif
PrintString(cmd,
DIMA(cmd),
"sd.exe -p %s print -o %s -q %s",
translate(me, sdf->depot, depot),
target,
translate(me, sdf->loc, loc));
// execute the source depot command
ZeroMemory((void *)&si, sizeof(si));
rc = CreateProcess(NULL,
cmd,
NULL,
NULL,
false,
0,
NULL,
pe->path,
&si,
&pi);
if (!rc)
*target = 0;
return rc;
}