Hi.
I ask for comments before sending this as 2 or 3 patches.
- Correct 2 failing tests on win9x
- Add Documentation for GetPrinterDriverDirectoryW/A (c2man)
- Add Function "validate_envW" to validate the user-supplied
Printing Environment (respect "Windows Version" - Setting)
- Change GetPrinterDriverDirectoryW to Report the correct NT-Path
or the win9x-Path on top of "validate_envW"
- Fix 2 Bugs in GetPrinterDriverDirectoryA
(invalid Result from "needed" and possible Read from 0x00000000)
- 2 Tests are now working in Wine
"validate_envW" will be used by more Functions later.
(WINSPOOL_OpenDriverReg as Example)
--
By By ...
... Detlef
Index: dlls/winspool/info.c
===================================================================
RCS file: /home/wine/wine/dlls/winspool/info.c,v
retrieving revision 1.130
diff -u -r1.130 info.c
--- dlls/winspool/info.c 24 Oct 2005 15:03:02 -0000 1.130
+++ dlls/winspool/info.c 22 Nov 2005 23:53:20 -0000
@@ -131,6 +131,14 @@
'D','e','v','i','c','e','s',0};
static const WCHAR DefaultEnvironmentW[] = {'W','i','n','e',0};
+static const WCHAR env_x86W[] = {'W','i','n','d','o','w','s',' ','N','T',' ','x','8','6',0};
+static const WCHAR env_win40W[] = {'W','i','n','d','o','w','s',' ','4','.','0',0};
+static const WCHAR subdir_x86W[] = {'w','3','2','x','8','6',0};
+static const WCHAR subdir_win40W[] = {'w','i','n','4','0',0};
+static const WCHAR spooldriversW[] = {'\\','s','p','o','o','l','\\','D','R','I','V','E','R','S','\\',0};
+
+static const LPCWSTR env_namesW[] = {NULL, env_win40W, env_x86W };
+static const LPCWSTR env_subdirW[] = {NULL, subdir_win40W, subdir_x86W };
static const WCHAR Configuration_FileW[] = {'C','o','n','f','i','g','u','r','a','t',
'i','o','n',' ','F','i','l','e',0};
@@ -605,6 +613,65 @@
}
+/******************************************************************
+ * validate the user-supplied printing-environment [internal]
+ *
+ * PARAMS
+ * LPCWSTR env [I] PTR to environment-String or NULL
+ *
+ * RETURNS
+ * Failure: 0
+ * Success: > 0 (ENVIRONMENT_WIN40 or ENVIRONMENT_X86)
+ *
+ * NOTES
+ * SetLastEror(ERROR_INVALID_ENVIRONMENT) is called on Failure
+ *
+ */
+
+static DWORD validate_envW(LPCWSTR env)
+{
+ DWORD rc = 0;
+
+ TRACE("testing %s\n", debugstr_w(env));
+
+ if (env) {
+ /* ENVIRONMENT_X86 is valid on NT only */
+ rc = ENVIRONMENT_X86;
+ while((rc > 0) && (lstrcmpiW(env, env_namesW[rc]) != 0)) {
+ rc--;
+ }
+ if (rc == 0) {
+ FIXME("unsupported Environment: %s\n", debugstr_w(env));
+ }
+ /* ENVIRONMENT_X86 is valid on NT only */
+ if ((rc > ENVIRONMENT_WIN40) && (GetVersion() & 0x80000000)) rc = 0;
+ }
+ else
+ {
+ OSVERSIONINFOW ver;
+ ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
+
+ if(GetVersionExW(&ver)) {
+ switch (ver.dwPlatformId) {
+ case VER_PLATFORM_WIN32s:
+ ERR("win32 style printing used with 16 bits app, try specifying 'win95' Windows version\n");
+ break;
+ case VER_PLATFORM_WIN32_NT:
+ rc = ENVIRONMENT_X86;
+ break;
+ default:
+ rc = ENVIRONMENT_WIN40;
+ break;
+ }
+ }
+ }
+
+ TRACE("using environment %ld: %s\n", rc, debugstr_w(env_namesW[rc]));
+ if (! rc) SetLastError(ERROR_INVALID_ENVIRONMENT);
+ return rc;
+}
+
+
/******************************************************************
* get_opened_printer_entry
@@ -3228,49 +3295,107 @@
/*****************************************************************************
* GetPrinterDriverDirectoryW [EMAIL PROTECTED]
+ *
+ * Return the PATH for the Printer-Drivers (UNICODE)
+ *
+ * PARAMS
+ * pName [I] Servername (NT only) or NULL (local Computer)
+ * pEnvironment [I] Printing-Environment (see below) or NULL
+ * Level [I] Structure-Level (must be 1)
+ * pDriverDirectory [O] PTR to Buffer that receives the Result
+ * cbBuf [I] Size of Buffer at pDriverDirectory
+ * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used /
+ * required for pDriverDirectory
+ *
+ *
+ * RETURNS
+ * Success: TRUE and in pcbNeeded the Bytes used in pDriverDirectory
+ * Failure: FALSE and in pcbNeeded the Bytes required for pDriverDirectory,
+ * if cbBuf is to small
+ *
+ * EXPECTED RESULTS
+ * win9x: "%winsysdir%"
+ * NT(Windows 4.0): "%winsysdir%\spool\DRIVERS\win40"
+ * NT(Windows NT x86): "%winsysdir%\spool\DRIVERS\w32x86"
+ *
+ * FIXME
+ * pName != NULL not supported
+ *
+ * NOTES
+ * Supported Printing-Environments:
+ * "Windows 4.0" (win9x) and "Windows NT x86" (NT on i386 and above)
+ *
*/
BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
DWORD Level, LPBYTE pDriverDirectory,
DWORD cbBuf, LPDWORD pcbNeeded)
{
- DWORD needed;
+ DWORD needed, env_index;
TRACE("(%s, %s, %ld, %p, %ld, %p)\n", debugstr_w(pName),
debugstr_w(pEnvironment), Level, pDriverDirectory, cbBuf, pcbNeeded);
if(pName != NULL) {
- FIXME("pName = `%s' - unsupported\n", debugstr_w(pName));
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- if(pEnvironment != NULL) {
- FIXME("pEnvironment = `%s' - unsupported\n", debugstr_w(pEnvironment));
- SetLastError(ERROR_INVALID_ENVIRONMENT);
- return FALSE;
+ FIXME("pName unsupported: %s\n", debugstr_w(pName));
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
}
- if(Level != 1) /* win95 ignores this so we just carry on */
+ env_index = validate_envW(pEnvironment);
+ if(!env_index) return FALSE; /* pEnvironment invalid or unsupported */
+
+ if(Level != 1) {
+ /* this is a failure on NT, but ignored in win9x */
+ if(GetVersion() < 0x80000000) {
+ SetLastError(ERROR_INVALID_LEVEL);
+ return FALSE;
+ }
WARN("Level = %ld - assuming 1\n", Level);
+ }
- /* FIXME should read from registry */
- needed = GetSystemDirectoryW( (LPWSTR)pDriverDirectory, cbBuf/sizeof(WCHAR));
- /* GetSystemDirectoryW returns number of TCHAR without '\0'
- * adjust this now
- */
- needed++;
- needed*=sizeof(WCHAR);
+ /* GetSystemDirectoryW returns number of WCHAR including the '\0' */
+ needed = GetSystemDirectoryW(NULL, 0);
+ /* add the Size for the Subdirectory on NT */
+ if(GetVersion() < 0x80000000) {
+ needed += lstrlenW(spooldriversW);
+ needed += lstrlenW(env_subdirW[env_index]);
+ }
+ needed*=sizeof(WCHAR); /* return size in Bytes */
if(pcbNeeded)
*pcbNeeded = needed;
- TRACE("required <%08lx>\n", *pcbNeeded);
+ TRACE("required: 0x%lx/%ld\n", needed, needed);
if(needed > cbBuf) {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
+ return FALSE;
+ }
+ if((pcbNeeded == NULL) && (GetVersion() < 0x80000000)) {
+ /* this is a failure on NT, but ignored in win9x */
+ SetLastError(RPC_X_NULL_REF_POINTER);
+ return FALSE;
+ }
+ if(pDriverDirectory == NULL) {
+ /* ERROR_INVALID_USER_BUFFER is NT, ERROR_INVALID_PARAMETER is win9x */
+ SetLastError((GetVersion() < 0x80000000) ?
+ ERROR_INVALID_USER_BUFFER : ERROR_INVALID_PARAMETER);
+ return FALSE;
}
+
+ GetSystemDirectoryW((LPWSTR) pDriverDirectory, cbBuf/sizeof(WCHAR));
+ /* add the Subdirectories on NT */
+ if(GetVersion() < 0x80000000) {
+ lstrcatW((LPWSTR) pDriverDirectory, spooldriversW);
+ lstrcatW((LPWSTR) pDriverDirectory, env_subdirW[env_index]);
+ }
+ TRACE(" => %s\n", debugstr_w((LPWSTR) pDriverDirectory));
return TRUE;
}
/*****************************************************************************
* GetPrinterDriverDirectoryA [EMAIL PROTECTED]
+ *
+ * Return the PATH for the Printer-Drivers (ANSI)
+ *
+ * See GetPrinterDriverDirectoryW.
*/
BOOL WINAPI GetPrinterDriverDirectoryA(LPSTR pName, LPSTR pEnvironment,
DWORD Level, LPBYTE pDriverDirectory,
@@ -3293,7 +3418,7 @@
(LPBYTE)driverDirectoryW, len, &pcbNeededW );
if (ret) {
DWORD needed;
- needed = 1 + WideCharToMultiByte( CP_ACP, 0, driverDirectoryW, -1,
+ needed = WideCharToMultiByte( CP_ACP, 0, driverDirectoryW, -1,
(LPSTR)pDriverDirectory, cbBuf, NULL, NULL);
if(pcbNeeded)
*pcbNeeded = needed;
@@ -3301,7 +3426,7 @@
} else
if(pcbNeeded) *pcbNeeded = pcbNeededW * sizeof(CHAR)/sizeof(WCHAR);
- TRACE("provided<%ld> required <%ld>\n", cbBuf, *pcbNeeded);
+ TRACE("required: %ld/0x%lx\n", pcbNeeded ? *pcbNeeded : -1, pcbNeeded ? *pcbNeeded : -1);
HeapFree( GetProcessHeap(), 0, driverDirectoryW );
RtlFreeUnicodeString(&environmentW);
Index: dlls/winspool/wspool.h
===================================================================
RCS file: /home/wine/wine/dlls/winspool/wspool.h,v
retrieving revision 1.1
diff -u -r1.1 wspool.h
--- dlls/winspool/wspool.h 12 Jul 2005 17:01:44 -0000 1.1
+++ dlls/winspool/wspool.h 22 Nov 2005 23:53:20 -0000
@@ -29,3 +29,8 @@
#define FILENAME_DIALOG 100
#define EDITBOX 201
+
+
+#define ENVIRONMENT_WIN40 1
+#define ENVIRONMENT_X86 2
+
Index: dlls/winspool/tests/info.c
===================================================================
RCS file: /home/wine/wine/dlls/winspool/tests/info.c,v
retrieving revision 1.11
diff -u -r1.11 info.c
--- dlls/winspool/tests/info.c 15 Nov 2005 16:51:45 -0000 1.11
+++ dlls/winspool/tests/info.c 22 Nov 2005 23:53:20 -0000
@@ -160,20 +160,20 @@
ok( !res , "expected result == 0, got %d\n", res);
ok( cbBuf == pcbNeeded, "pcbNeeded set to %ld instead of %ld\n",
pcbNeeded, cbBuf);
- todo_wine {
+
ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
"last error set to %ld instead of ERROR_INSUFFICIENT_BUFFER\n",
GetLastError());
- }
+
SetLastError(0x00dead00);
res = GetPrinterDriverDirectoryA( NULL, NULL, 1, NULL, cbBuf, &pcbNeeded);
ok( (!res && ERROR_INVALID_USER_BUFFER == GetLastError()) ||
+ ( res && ERROR_SUCCESS == GetLastError()) ||
( res && ERROR_INVALID_PARAMETER == GetLastError()) ,
- "expected either result == 0 and "
- "last error == ERROR_INVALID_USER_BUFFER "
- "or result != 0 and last error == ERROR_INVALID_PARAMETER "
- "got result %d and last error == %ld\n", res, GetLastError());
+ "returned %d with lasterror=%ld (expected "
+ "'0' with ERROR_INVALID_USER_BUFFER or '!= 0' with ERROR_SUCCESS or "
+ "'!= 0' with ERROR_INVALID_PARAMETER)\n", res, GetLastError());
SetLastError(0x00dead00);
res = GetPrinterDriverDirectoryA( NULL, NULL, 1, buffer, cbBuf, NULL);
@@ -185,11 +185,11 @@
SetLastError(0x00dead00);
res = GetPrinterDriverDirectoryA( NULL, NULL, 1, NULL, cbBuf, NULL);
ok( (!res && RPC_X_NULL_REF_POINTER == GetLastError()) ||
+ ( res && ERROR_SUCCESS == GetLastError()) ||
( res && ERROR_INVALID_PARAMETER == GetLastError()) ,
- "expected either result == 0 and "
- "last error == RPC_X_NULL_REF_POINTER "
- "or result != 0 and last error == ERROR_INVALID_PARAMETER "
- "got result %d and last error == %ld\n", res, GetLastError());
+ "returned %d with lasterror=%ld (expected "
+ "'0' with RPC_X_NULL_REF_POINTER or '!= 0' with ERROR_SUCCESS or "
+ "'!= 0' with ERROR_INVALID_PARAMETER)\n", res, GetLastError());
/* with a valid buffer, but level is to large */
buffer[0] = '\0';
@@ -226,11 +226,11 @@
buffer, cbBuf*2, &pcbNeeded);
}
- todo_wine{
+
ok(res && buffer[0], "returned %d with " \
- "lasterror=%ld and len=%d (expected '0' with 'len > 0')\n",
+ "lasterror=%ld and len=%d (expected '1' with 'len > 0')\n",
res, GetLastError(), lstrlenA((char *)buffer));
- }
+
buffer[0] = '\0';
SetLastError(0x00dead00);